aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
authoronefang2019-09-11 16:36:50 +1000
committeronefang2019-09-11 16:36:50 +1000
commit50cd1ffd32f69228e566f2b0b89f86ea0d9fe489 (patch)
tree52f2ab0c04f1a5d7d6ac5dc872981b4b156447e7 /OpenSim/Region/CoreModules
parentRenamed branch to SledjChisl. (diff)
parentBump to release flavour, build 0. (diff)
downloadopensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.zip
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.gz
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.bz2
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.xz
Merge branch 'SledjChisl'
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs30
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs295
-rw-r--r--OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs4
-rw-r--r--OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs365
-rw-r--r--OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs38
-rw-r--r--OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs23
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs373
-rw-r--r--OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs24
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs377
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs92
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs616
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs18
-rw-r--r--OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs97
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs293
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs169
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs17
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs58
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs20
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs213
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs69
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs297
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs229
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs132
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs239
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs297
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs38
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs42
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs217
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs120
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs84
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs60
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs74
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs236
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs178
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs163
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs220
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs988
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs150
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs1675
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs44
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs84
-rw-r--r--OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs20
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs8
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs90
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs557
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs9
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs64
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs15
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs148
-rw-r--r--OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs14
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs345
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs10
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs147
-rw-r--r--OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs261
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs22
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs542
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs56
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs48
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs122
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs124
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs33
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs36
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/LocalAgentPreferencesServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/RemoteAgentPreferencesServiceConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs73
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs44
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs11
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs11
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs9
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs20
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs8
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs164
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs102
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs965
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs154
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs35
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs70
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs18
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs16
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs25
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs52
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MuteList/LocalMuteListServiceConnector.cs188
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MuteList/RemoteMuteListServiceConnector.cs (renamed from OpenSim/Region/ClientStack/Linden/Caps/GetDisplayNamesModule.cs)141
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/NeighbourServiceOutConnector.cs (renamed from OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs)83
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs157
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs5
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs18
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs10
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs17
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs55
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs61
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs103
-rw-r--r--OpenSim/Region/CoreModules/World/Access/AccessModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs363
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs122
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs232
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs39
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs209
-rw-r--r--OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs86
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateConnector.cs (renamed from OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs)62
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs38
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs663
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateModule.cs (renamed from OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs)64
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs (renamed from OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs)24
-rw-r--r--OpenSim/Region/CoreModules/World/Land/DwellModule.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs62
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs1333
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs883
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs177
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs40
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs224
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs53
-rw-r--r--OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs255
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs36
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs120
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2054
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs91
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs186
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs174
-rw-r--r--OpenSim/Region/CoreModules/World/Sun/SunModule.cs12
-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/BMP.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs81
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs14
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs10
-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/ITerrainLoader.cs2
-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.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs30
-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.cs32
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs14
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs20
-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.cs704
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs381
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs19
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs21
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs167
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs1601
213 files changed, 16265 insertions, 9543 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index f56d17d..f48710f 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -127,7 +127,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
127 if (estateModule.IsTerrainXfer(xferID)) 127 if (estateModule.IsTerrainXfer(xferID))
128 return; 128 return;
129 } 129 }
130 130
131 m_log.ErrorFormat( 131 m_log.ErrorFormat(
132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", 132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
133 xferID, packetID, data.Length); 133 xferID, packetID, data.Length);
@@ -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..7d9f3b3 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
43 IAgentAssetTransactions 43 IAgentAssetTransactions
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 protected Scene m_Scene; 47 protected Scene m_Scene;
48 private bool m_dumpAssetsToFile = false; 48 private bool m_dumpAssetsToFile = false;
49 private int m_levelUpload = 0; 49 private int m_levelUpload = 0;
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
53 /// </summary> 53 /// </summary>
54 private Dictionary<UUID, AgentAssetTransactions> AgentTransactions = 54 private Dictionary<UUID, AgentAssetTransactions> AgentTransactions =
55 new Dictionary<UUID, AgentAssetTransactions>(); 55 new Dictionary<UUID, AgentAssetTransactions>();
56 56
57 #region Region Module interface 57 #region Region Module interface
58 58
59 public void Initialise(IConfigSource source) 59 public void Initialise(IConfigSource source)
@@ -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 }
@@ -241,7 +241,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
241// m_log.DebugFormat( 241// m_log.DebugFormat(
242// "[ASSET TRANSACTION MODULE]: HandleUDPUploadRequest - assetID: {0}, transaction {1}, type {2}, storeLocal {3}, tempFile {4}, data.Length {5}", 242// "[ASSET TRANSACTION MODULE]: HandleUDPUploadRequest - assetID: {0}, transaction {1}, type {2}, storeLocal {3}, tempFile {4}, data.Length {5}",
243// assetID, transactionID, type, storeLocal, tempFile, data.Length); 243// assetID, transactionID, type, storeLocal, tempFile, data.Length);
244 244
245 if (((AssetType)type == AssetType.Texture || 245 if (((AssetType)type == AssetType.Texture ||
246 (AssetType)type == AssetType.Sound || 246 (AssetType)type == AssetType.Sound ||
247 (AssetType)type == AssetType.TextureTGA || 247 (AssetType)type == AssetType.TextureTGA ||
@@ -255,7 +255,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
255 // check user level 255 // check user level
256 if (avatar != null) 256 if (avatar != null)
257 { 257 {
258 if (avatar.UserLevel < m_levelUpload) 258 if (avatar.GodController.UserLevel < m_levelUpload)
259 { 259 {
260 remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 260 remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
261 return; 261 return;
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index 5143204..52b9d0e 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,23 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40{ 41{
41 public class AssetXferUploader 42 public class AssetXferUploader
42 { 43 {
44
45 private List<UUID> defaultIDs = new List<UUID> {
46 // Viewer's notion of the default texture
47 new UUID("5748decc-f629-461c-9a36-a35a221fe21f"), // others == default blank
48 new UUID("7ca39b4c-bd19-4699-aff7-f93fd03d3e7b"), // hair
49 new UUID("6522e74d-1660-4e7f-b601-6f48c1659a77"), // eyes
50 new UUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"), // skin
51 new UUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"), // transparency for alpha
52 // opensim assets textures possibly obsolete now
53 new UUID("00000000-0000-1111-9999-000000000010"),
54 new UUID("00000000-0000-1111-9999-000000000011"),
55 new UUID("00000000-0000-1111-9999-000000000012"),
56 // other transparency defined in assets
57 new UUID("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"),
58 new UUID("1578a2b1-5179-4b53-b618-fe00ca5a5594"),
59 };
60
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 62
45 /// <summary> 63 /// <summary>
@@ -87,6 +105,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
87 105
88 private sbyte type = 0; 106 private sbyte type = 0;
89 private byte wearableType = 0; 107 private byte wearableType = 0;
108 private byte[] m_oldData = null;
90 public ulong XferID; 109 public ulong XferID;
91 private Scene m_Scene; 110 private Scene m_Scene;
92 111
@@ -129,18 +148,27 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
129 148
130 if (XferID == xferID) 149 if (XferID == xferID)
131 { 150 {
132 if (m_asset.Data.Length > 1) 151 lock (this)
133 {
134 byte[] destinationArray = new byte[m_asset.Data.Length + data.Length];
135 Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length);
136 Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length);
137 m_asset.Data = destinationArray;
138 }
139 else
140 { 152 {
141 byte[] buffer2 = new byte[data.Length - 4]; 153 int assetLength = m_asset.Data.Length;
142 Array.Copy(data, 4, buffer2, 0, data.Length - 4); 154 int dataLength = data.Length;
143 m_asset.Data = buffer2; 155
156 if (m_asset.Data.Length > 1)
157 {
158 byte[] destinationArray = new byte[assetLength + dataLength];
159 Array.Copy(m_asset.Data, 0, destinationArray, 0, assetLength);
160 Array.Copy(data, 0, destinationArray, assetLength, dataLength);
161 m_asset.Data = destinationArray;
162 }
163 else
164 {
165 if (dataLength > 4)
166 {
167 byte[] buffer2 = new byte[dataLength - 4];
168 Array.Copy(data, 4, buffer2, 0, dataLength - 4);
169 m_asset.Data = buffer2;
170 }
171 }
144 } 172 }
145 173
146 ourClient.SendConfirmXfer(xferID, packetID); 174 ourClient.SendConfirmXfer(xferID, packetID);
@@ -230,24 +258,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
230 { 258 {
231 m_uploadState = UploadState.Complete; 259 m_uploadState = UploadState.Complete;
232 260
233 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); 261 bool sucess = true;
234
235 if (m_createItem) 262 if (m_createItem)
236 { 263 {
237 CompleteCreateItem(m_createItemCallback); 264 sucess = CompleteCreateItem(m_createItemCallback);
238 } 265 }
239 else if (m_updateItem) 266 else if (m_updateItem)
240 { 267 {
241 CompleteItemUpdate(m_updateItemData); 268 sucess = CompleteItemUpdate(m_updateItemData);
242 } 269 }
243 else if (m_updateTaskItem) 270 else if (m_updateTaskItem)
244 { 271 {
245 CompleteTaskItemUpdate(m_updateTaskItemData); 272 sucess = CompleteTaskItemUpdate(m_updateTaskItemData);
246 } 273 }
247// else if (m_storeLocal) 274 else if (m_asset.Local)
248// { 275 {
249// m_Scene.AssetService.Store(m_asset); 276 m_Scene.AssetService.Store(m_asset);
250// } 277 }
278 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, sucess, m_asset.FullID);
251 } 279 }
252 280
253 m_log.DebugFormat( 281 m_log.DebugFormat(
@@ -319,14 +347,16 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
319 m_asset.Description = item.Description; 347 m_asset.Description = item.Description;
320 m_asset.Type = (sbyte)item.AssetType; 348 m_asset.Type = (sbyte)item.AssetType;
321 349
322 if (m_asset.FullID != UUID.Zero) 350 // remove redundante m_Scene.InventoryService.UpdateItem
323 { 351 // if uploadState == UploadState.Complete)
352// if (m_asset.FullID != UUID.Zero)
353// {
324 // We must always store the item at this point even if the asset hasn't finished uploading, in order 354 // 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 355 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
326 // the AvatarAppearance structure. 356 // the AvatarAppearance structure.
327 item.AssetID = m_asset.FullID; 357// item.AssetID = m_asset.FullID;
328 m_Scene.InventoryService.UpdateItem(item); 358// m_Scene.InventoryService.UpdateItem(item);
329 } 359// }
330 360
331 if (m_uploadState == UploadState.Complete) 361 if (m_uploadState == UploadState.Complete)
332 { 362 {
@@ -334,10 +364,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
334 } 364 }
335 else 365 else
336 { 366 {
337// m_log.DebugFormat( 367 // 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}", 368 if (m_asset.FullID != UUID.Zero)
339// item.Name, remoteClient.Name, transactionID); 369 {
340 370 // We must always store the item at this point even if the asset hasn't finished uploading, in order
371 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
372 // the AvatarAppearance structure.
373 item.AssetID = m_asset.FullID;
374 m_Scene.InventoryService.UpdateItem(item);
375 }
376
377
378 // m_log.DebugFormat(
379 // "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}",
380 // item.Name, remoteClient.Name, transactionID);
381
341 m_updateItem = true; 382 m_updateItem = true;
342 m_updateItemData = item; 383 m_updateItemData = item;
343 } 384 }
@@ -370,36 +411,70 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
370 /// Store the asset for the given item when it has been uploaded. 411 /// Store the asset for the given item when it has been uploaded.
371 /// </summary> 412 /// </summary>
372 /// <param name="item"></param> 413 /// <param name="item"></param>
373 private void CompleteItemUpdate(InventoryItemBase item) 414 private bool CompleteItemUpdate(InventoryItemBase item)
374 { 415 {
375// m_log.DebugFormat( 416// m_log.DebugFormat(
376// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", 417// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
377// m_asset.FullID, item.Name, ourClient.Name); 418// m_asset.FullID, item.Name, ourClient.Name);
378 419
379 m_Scene.AssetService.Store(m_asset); 420 uint perms = ValidateAssets();
380 421 if(perms == 0)
381 m_transactions.RemoveXferUploader(m_transactionID); 422 {
423 string error = string.Format("Not enough permissions on asset(s) referenced by item '{0}', update failed", item.Name);
424 ourClient.SendAlertMessage(error);
425 m_transactions.RemoveXferUploader(m_transactionID);
426 ourClient.SendBulkUpdateInventory(item); // invalid the change item on viewer cache
427 }
428 else
429 {
430 m_Scene.AssetService.Store(m_asset);
431 if (m_asset.FullID != UUID.Zero)
432 {
433 item.AssetID = m_asset.FullID;
434 m_Scene.InventoryService.UpdateItem(item);
435 }
436 ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0);
437 m_transactions.RemoveXferUploader(m_transactionID);
438 m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(item, 0);
439 }
382 440
383 m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(ourClient.AgentId, (AssetType)type, m_asset.FullID, m_asset.Name, 0); 441 return perms != 0;
384 } 442 }
385 443
386 /// <summary> 444 /// <summary>
387 /// Store the asset for the given task item when it has been uploaded. 445 /// Store the asset for the given task item when it has been uploaded.
388 /// </summary> 446 /// </summary>
389 /// <param name="taskItem"></param> 447 /// <param name="taskItem"></param>
390 private void CompleteTaskItemUpdate(TaskInventoryItem taskItem) 448 private bool CompleteTaskItemUpdate(TaskInventoryItem taskItem)
391 { 449 {
392// m_log.DebugFormat( 450// m_log.DebugFormat(
393// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", 451// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
394// m_asset.FullID, taskItem.Name, ourClient.Name); 452// m_asset.FullID, taskItem.Name, ourClient.Name);
395 453
396 m_Scene.AssetService.Store(m_asset); 454 if(ValidateAssets() == 0)
455 {
456 m_transactions.RemoveXferUploader(m_transactionID);
457 string error = string.Format("Not enough permissions on asset(s) referenced by task item '{0}', update failed", taskItem.Name);
458 ourClient.SendAlertMessage(error);
459 // force old asset to viewers ??
460 return false;
461 }
397 462
463 m_Scene.AssetService.Store(m_asset);
398 m_transactions.RemoveXferUploader(m_transactionID); 464 m_transactions.RemoveXferUploader(m_transactionID);
465 return true;
399 } 466 }
400 467
401 private void CompleteCreateItem(uint callbackID) 468 private bool CompleteCreateItem(uint callbackID)
402 { 469 {
470 if(ValidateAssets() == 0)
471 {
472 m_transactions.RemoveXferUploader(m_transactionID);
473 string error = string.Format("Not enough permissions on asset(s) referenced by item '{0}', creation failed", m_name);
474 ourClient.SendAlertMessage(error);
475 return false;
476 }
477
403 m_Scene.AssetService.Store(m_asset); 478 m_Scene.AssetService.Store(m_asset);
404 479
405 InventoryItemBase item = new InventoryItemBase(); 480 InventoryItemBase item = new InventoryItemBase();
@@ -420,13 +495,155 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
420 item.Flags = (uint) wearableType; 495 item.Flags = (uint) wearableType;
421 item.CreationDate = Util.UnixTimeSinceEpoch(); 496 item.CreationDate = Util.UnixTimeSinceEpoch();
422 497
498 m_log.DebugFormat("[XFER]: Created item {0} with asset {1}",
499 item.ID, item.AssetID);
500
423 if (m_Scene.AddInventoryItem(item)) 501 if (m_Scene.AddInventoryItem(item))
424 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 502 ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, callbackID);
425 else 503 else
426 ourClient.SendAlertMessage("Unable to create inventory item"); 504 ourClient.SendAlertMessage("Unable to create inventory item");
427 505
428 m_transactions.RemoveXferUploader(m_transactionID); 506 m_transactions.RemoveXferUploader(m_transactionID);
507 return true;
508 }
509
510 private uint ValidateAssets()
511 {
512 uint retPerms = 0x7fffffff;
513// if(m_Scene.Permissions.BypassPermissions())
514// return retPerms;
515
516 if (m_asset.Type == (sbyte)CustomAssetType.AnimationSet)
517 {
518
519 AnimationSet animSet = new AnimationSet(m_asset.Data);
520
521 retPerms &= animSet.Validate(x => {
522 const uint required = (uint)(PermissionMask.Transfer | PermissionMask.Copy);
523 uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x);
524 // currrent yes/no rule
525 if ((perms & required) != required)
526 return 0;
527 return perms;
528 });
529
530 return retPerms;
531 }
532
533 if (m_asset.Type == (sbyte)AssetType.Clothing ||
534 m_asset.Type == (sbyte)AssetType.Bodypart)
535 {
536 const uint texturesfullPermMask = (uint)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
537 string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
538 string[] lines = content.Split(new char[] {'\n'});
539
540 // on current requiriment of full rigths assume old assets where accepted
541 Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
542
543 int textures = 0;
544
545 foreach (string line in lines)
546 {
547 try
548 {
549 if (line.StartsWith("textures "))
550 textures = Convert.ToInt32(line.Substring(9));
551
552 else if (textures > 0)
553 {
554 string[] parts = line.Split(new char[] {' '});
555
556 UUID tx = new UUID(parts[1]);
557 int id = Convert.ToInt32(parts[0]);
558
559 if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
560 (allowed.ContainsKey(id) && allowed[id] == tx))
561 {
562 continue;
563 }
564 else
565 {
566 uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
567
568 if ((perms & texturesfullPermMask) != texturesfullPermMask)
569 {
570 m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
571 return 0;
572 }
573 else
574 {
575 retPerms &= perms;
576 }
577 }
578 textures--;
579 }
580 }
581 catch
582 {
583 // If it's malformed, skip it
584 }
585 }
586 }
587 return retPerms;
588 }
589
590/* not in use
591 /// <summary>
592 /// Get the asset data uploaded in this transfer.
593 /// </summary>
594 /// <returns>null if the asset has not finished uploading</returns>
595 public AssetBase GetAssetData()
596 {
597 if (m_uploadState == UploadState.Complete)
598 {
599 ValidateAssets();
600 return m_asset;
601 }
602
603 return null;
604 }
605*/
606 public void SetOldData(byte[] d)
607 {
608 m_oldData = d;
429 } 609 }
430 610
611 private Dictionary<int,UUID> ExtractTexturesFromOldData()
612 {
613 Dictionary<int,UUID> result = new Dictionary<int,UUID>();
614 if (m_oldData == null)
615 return result;
616
617 string content = System.Text.Encoding.ASCII.GetString(m_oldData);
618 string[] lines = content.Split(new char[] {'\n'});
619
620 int textures = 0;
621
622 foreach (string line in lines)
623 {
624 try
625 {
626 if (line.StartsWith("textures "))
627 {
628 textures = Convert.ToInt32(line.Substring(9));
629 }
630 else if (textures > 0)
631 {
632 string[] parts = line.Split(new char[] {' '});
633
634 UUID tx = new UUID(parts[1]);
635 int id = Convert.ToInt32(parts[0]);
636 result[id] = tx;
637 textures--;
638 }
639 }
640 catch
641 {
642 // If it's malformed, skip it
643 }
644 }
645
646 return result;
647 }
431 } 648 }
432} \ No newline at end of file 649}
diff --git a/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs b/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs
index 4b457b1..ff71593 100644
--- a/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs
@@ -38,7 +38,7 @@ using OpenSim.Region.Framework.Scenes;
38namespace OpenSim.Region.CoreModules.Agent.IPBan 38namespace OpenSim.Region.CoreModules.Agent.IPBan
39{ 39{
40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "IPBanModule")] 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "IPBanModule")]
41 public class IPBanModule : ISharedRegionModule 41 public class IPBanModule : ISharedRegionModule
42 { 42 {
43 #region Implementation of ISharedRegionModule 43 #region Implementation of ISharedRegionModule
44 44
@@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan
86 86
87 public void Close() 87 public void Close()
88 { 88 {
89 89
90 } 90 }
91 91
92 public string Name 92 public string Name
@@ -107,9 +107,9 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan
107 /// matching domain (including "betasomewhere.com", "beta.somewhere.com", 107 /// matching domain (including "betasomewhere.com", "beta.somewhere.com",
108 /// "somewhere.com.beta") - make sure to be reasonably specific in DNS 108 /// "somewhere.com.beta") - make sure to be reasonably specific in DNS
109 /// bans. 109 /// bans.
110 /// 110 ///
111 /// IP address bans match on first characters, so, 111 /// IP address bans match on first characters, so,
112 /// "127.0.0.1" will ban only that address, 112 /// "127.0.0.1" will ban only that address,
113 /// "127.0.1" will ban "127.0.10.0" 113 /// "127.0.1" will ban "127.0.10.0"
114 /// but "127.0.1." will ban only the "127.0.1.*" network 114 /// but "127.0.1." will ban only the "127.0.1.*" network
115 /// </summary> 115 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs b/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs
index 8502006..b4c68e2 100644
--- a/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs
+++ b/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs
@@ -53,9 +53,9 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan
53 if (bans.Count > 0) 53 if (bans.Count > 0)
54 { 54 {
55 IClientIPEndpoint ipEndpoint; 55 IClientIPEndpoint ipEndpoint;
56 if (client.TryGet(out ipEndpoint)) 56 if (client.TryGet(out ipEndpoint) && ipEndpoint.RemoteEndPoint != null)
57 { 57 {
58 IPAddress end = ipEndpoint.EndPoint; 58 IPAddress end = ipEndpoint.RemoteEndPoint.Address;
59 59
60 try 60 try
61 { 61 {
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
index 47dcbcd..6e4a710 100644
--- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
@@ -57,13 +57,13 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
57 /// <summary>List of client methods to notify of results of decode</summary> 57 /// <summary>List of client methods to notify of results of decode</summary>
58 private readonly Dictionary<UUID, List<DecodedCallback>> m_notifyList = new Dictionary<UUID, List<DecodedCallback>>(); 58 private readonly Dictionary<UUID, List<DecodedCallback>> m_notifyList = new Dictionary<UUID, List<DecodedCallback>>();
59 /// <summary>Cache that will store decoded JPEG2000 layer boundary data</summary> 59 /// <summary>Cache that will store decoded JPEG2000 layer boundary data</summary>
60 private IImprovedAssetCache m_cache; 60 private IAssetCache m_cache;
61 private IImprovedAssetCache Cache 61 private IAssetCache Cache
62 { 62 {
63 get 63 get
64 { 64 {
65 if (m_cache == null) 65 if (m_cache == null)
66 m_cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 66 m_cache = m_scene.RequestModuleInterface<IAssetCache>();
67 67
68 return m_cache; 68 return m_cache;
69 } 69 }
@@ -285,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
285 // Cache Decoded layers 285 // Cache Decoded layers
286 SaveFileCacheForAsset(assetID, layers); 286 SaveFileCacheForAsset(assetID, layers);
287 } 287 }
288 288
289 // Notify Interested Parties 289 // Notify Interested Parties
290 lock (m_notifyList) 290 lock (m_notifyList)
291 { 291 {
@@ -369,7 +369,8 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
369 else if (Cache != null) 369 else if (Cache != null)
370 { 370 {
371 string assetName = "j2kCache_" + AssetId.ToString(); 371 string assetName = "j2kCache_" + AssetId.ToString();
372 AssetBase layerDecodeAsset = Cache.Get(assetName); 372 AssetBase layerDecodeAsset;
373 Cache.Get(assetName, out layerDecodeAsset);
373 374
374 if (layerDecodeAsset != null) 375 if (layerDecodeAsset != null)
375 { 376 {
diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
index 4299726..1b6401a 100644
--- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
@@ -28,10 +28,12 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading;
31using Nini.Config; 32using Nini.Config;
32using log4net; 33using log4net;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Monitoring;
35using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
37 39
@@ -45,9 +47,13 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
45 private Scene m_scene; 47 private Scene m_scene;
46 private Dictionary<string, FileData> NewFiles = new Dictionary<string, FileData>(); 48 private Dictionary<string, FileData> NewFiles = new Dictionary<string, FileData>();
47 private Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>(); 49 private Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>();
48
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 51
52 private object timeTickLock = new object();
53 private double lastTimeTick = 0.0;
54 private double lastFilesExpire = 0.0;
55 private bool inTimeTick = false;
56
51 public struct XferRequest 57 public struct XferRequest
52 { 58 {
53 public IClientAPI remoteClient; 59 public IClientAPI remoteClient;
@@ -59,26 +65,30 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
59 private class FileData 65 private class FileData
60 { 66 {
61 public byte[] Data; 67 public byte[] Data;
62 public int Count; 68 public int refsCount;
69 public double timeStampMS;
63 } 70 }
64 71
65 #region INonSharedRegionModule Members 72 #region INonSharedRegionModule Members
66 73
67 public void Initialise(IConfigSource config) 74 public void Initialise(IConfigSource config)
68 { 75 {
76 lastTimeTick = Util.GetTimeStampMS() + 30000.0;
77 lastFilesExpire = lastTimeTick + 180000.0;
69 } 78 }
70 79
71 public void AddRegion(Scene scene) 80 public void AddRegion(Scene scene)
72 { 81 {
73 m_scene = scene; 82 m_scene = scene;
74 m_scene.EventManager.OnNewClient += NewClient;
75
76 m_scene.RegisterModuleInterface<IXfer>(this); 83 m_scene.RegisterModuleInterface<IXfer>(this);
84 m_scene.EventManager.OnNewClient += NewClient;
85 m_scene.EventManager.OnRegionHeartbeatEnd += OnTimeTick;
77 } 86 }
78 87
79 public void RemoveRegion(Scene scene) 88 public void RemoveRegion(Scene scene)
80 { 89 {
81 m_scene.EventManager.OnNewClient -= NewClient; 90 m_scene.EventManager.OnNewClient -= NewClient;
91 m_scene.EventManager.OnRegionHeartbeatEnd -= OnTimeTick;
82 92
83 m_scene.UnregisterModuleInterface<IXfer>(this); 93 m_scene.UnregisterModuleInterface<IXfer>(this);
84 m_scene = null; 94 m_scene = null;
@@ -104,6 +114,41 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
104 114
105 #endregion 115 #endregion
106 116
117 public void OnTimeTick(Scene scene)
118 {
119 // we are on a heartbeat thread we there can be several
120 if(Monitor.TryEnter(timeTickLock))
121 {
122 if(!inTimeTick)
123 {
124 double now = Util.GetTimeStampMS();
125 if(now - lastTimeTick > 1750.0)
126 {
127
128 if(Transfers.Count == 0 && NewFiles.Count == 0)
129 lastTimeTick = now;
130 else
131 {
132 inTimeTick = true;
133
134 //don't overload busy heartbeat
135 WorkManager.RunInThreadPool(
136 delegate
137 {
138 transfersTimeTick(now);
139 expireFiles(now);
140
141 lastTimeTick = now;
142 inTimeTick = false;
143 },
144 null,
145 "XferTimeTick");
146 }
147 }
148 }
149 Monitor.Exit(timeTickLock);
150 }
151 }
107 #region IXfer Members 152 #region IXfer Members
108 153
109 /// <summary> 154 /// <summary>
@@ -118,24 +163,45 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
118 { 163 {
119 lock (NewFiles) 164 lock (NewFiles)
120 { 165 {
166 double now = Util.GetTimeStampMS();
121 if (NewFiles.ContainsKey(fileName)) 167 if (NewFiles.ContainsKey(fileName))
122 { 168 {
123 NewFiles[fileName].Count++; 169 NewFiles[fileName].refsCount++;
124 NewFiles[fileName].Data = data; 170 NewFiles[fileName].Data = data;
171 NewFiles[fileName].timeStampMS = now;
125 } 172 }
126 else 173 else
127 { 174 {
128 FileData fd = new FileData(); 175 FileData fd = new FileData();
129 fd.Count = 1; 176 fd.refsCount = 1;
130 fd.Data = data; 177 fd.Data = data;
178 fd.timeStampMS = now;
131 NewFiles.Add(fileName, fd); 179 NewFiles.Add(fileName, fd);
132 } 180 }
133 } 181 }
134
135 return true; 182 return true;
136 } 183 }
137 184
138 #endregion 185 #endregion
186 public void expireFiles(double now)
187 {
188 lock (NewFiles)
189 {
190 // hopefully we will not have many files so nasty code will do it
191 if(now - lastFilesExpire > 120000.0)
192 {
193 lastFilesExpire = now;
194 List<string> expires = new List<string>();
195 foreach(string fname in NewFiles.Keys)
196 {
197 if(NewFiles[fname].refsCount == 0 && now - NewFiles[fname].timeStampMS > 120000.0)
198 expires.Add(fname);
199 }
200 foreach(string fname in expires)
201 NewFiles.Remove(fname);
202 }
203 }
204 }
139 205
140 public void NewClient(IClientAPI client) 206 public void NewClient(IClientAPI client)
141 { 207 {
@@ -144,6 +210,51 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
144 client.OnAbortXfer += AbortXfer; 210 client.OnAbortXfer += AbortXfer;
145 } 211 }
146 212
213 public void OnClientClosed(IClientAPI client)
214 {
215 client.OnRequestXfer -= RequestXfer;
216 client.OnConfirmXfer -= AckPacket;
217 client.OnAbortXfer -= AbortXfer;
218 }
219
220 private void RemoveOrDecrementFile(string fileName)
221 {
222 // NewFiles must be locked
223
224 if (NewFiles.ContainsKey(fileName))
225 {
226 if (NewFiles[fileName].refsCount == 1)
227 NewFiles.Remove(fileName);
228 else
229 NewFiles[fileName].refsCount--;
230 }
231 }
232
233 public void transfersTimeTick(double now)
234 {
235 XferDownLoad[] xfrs;
236 lock(Transfers)
237 {
238 if(Transfers.Count == 0)
239 return;
240
241 xfrs = new XferDownLoad[Transfers.Count];
242 Transfers.Values.CopyTo(xfrs,0);
243 }
244 foreach(XferDownLoad xfr in xfrs)
245 {
246 if(xfr.checkTime(now))
247 {
248 ulong xfrID = xfr.XferID;
249 lock(Transfers)
250 {
251 if(Transfers.ContainsKey(xfrID))
252 Transfers.Remove(xfrID);
253 }
254 }
255 }
256 }
257
147 /// <summary> 258 /// <summary>
148 /// 259 ///
149 /// </summary> 260 /// </summary>
@@ -156,78 +267,52 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
156 { 267 {
157 if (NewFiles.ContainsKey(fileName)) 268 if (NewFiles.ContainsKey(fileName))
158 { 269 {
159 if (!Transfers.ContainsKey(xferID)) 270 lock(Transfers)
160 { 271 {
161 byte[] fileData = NewFiles[fileName].Data; 272 if (!Transfers.ContainsKey(xferID))
162 XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); 273 {
163 274 byte[] fileData = NewFiles[fileName].Data;
164 Transfers.Add(xferID, transaction); 275 int burstSize = remoteClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset) >> 11;
165 276 if(Transfers.Count > 1)
166 if (transaction.StartSend()) 277 burstSize /= Transfers.Count;
167 RemoveXferData(xferID); 278 XferDownLoad transaction =
168 279 new XferDownLoad(fileName, fileData, xferID, remoteClient, burstSize);
169 // The transaction for this file is either complete or on its way 280
170 RemoveOrDecrement(fileName); 281 Transfers.Add(xferID, transaction);
171 282
283 transaction.StartSend();
284
285 // The transaction for this file is on its way
286 RemoveOrDecrementFile(fileName);
287 }
172 } 288 }
173 } 289 }
174 else 290 else
175 m_log.WarnFormat("[Xfer]: {0} not found", fileName); 291 m_log.WarnFormat("[Xfer]: {0} not found", fileName);
176
177 } 292 }
178 } 293 }
179 294
180 public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) 295 public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet)
181 { 296 {
182 lock (NewFiles) // This is actually to lock Transfers 297 lock (Transfers)
183 { 298 {
184 if (Transfers.ContainsKey(xferID)) 299 if (Transfers.ContainsKey(xferID))
185 { 300 {
186 XferDownLoad dl = Transfers[xferID];
187 if (Transfers[xferID].AckPacket(packet)) 301 if (Transfers[xferID].AckPacket(packet))
188 { 302 Transfers.Remove(xferID);
189 RemoveXferData(xferID);
190 RemoveOrDecrement(dl.FileName);
191 }
192 } 303 }
193 } 304 }
194 } 305 }
195 306
196 private void RemoveXferData(ulong xferID)
197 {
198 // NewFiles must be locked!
199 if (Transfers.ContainsKey(xferID))
200 {
201 XferModule.XferDownLoad xferItem = Transfers[xferID];
202 //string filename = xferItem.FileName;
203 Transfers.Remove(xferID);
204 xferItem.Data = new byte[0]; // Clear the data
205 xferItem.DataPointer = 0;
206
207 }
208 }
209
210 public void AbortXfer(IClientAPI remoteClient, ulong xferID) 307 public void AbortXfer(IClientAPI remoteClient, ulong xferID)
211 { 308 {
212 lock (NewFiles) 309 lock (Transfers)
213 { 310 {
214 if (Transfers.ContainsKey(xferID)) 311 if (Transfers.ContainsKey(xferID))
215 RemoveOrDecrement(Transfers[xferID].FileName); 312 {
216 313 Transfers[xferID].done();
217 RemoveXferData(xferID); 314 Transfers.Remove(xferID);
218 } 315 }
219 }
220
221 private void RemoveOrDecrement(string fileName)
222 {
223 // NewFiles must be locked
224
225 if (NewFiles.ContainsKey(fileName))
226 {
227 if (NewFiles[fileName].Count == 1)
228 NewFiles.Remove(fileName);
229 else
230 NewFiles[fileName].Count--;
231 } 316 }
232 } 317 }
233 318
@@ -236,52 +321,124 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
236 public class XferDownLoad 321 public class XferDownLoad
237 { 322 {
238 public IClientAPI Client; 323 public IClientAPI Client;
239 private bool complete;
240 public byte[] Data = new byte[0]; 324 public byte[] Data = new byte[0];
241 public int DataPointer = 0;
242 public string FileName = String.Empty; 325 public string FileName = String.Empty;
243 public uint Packet = 0;
244 public uint Serial = 1;
245 public ulong XferID = 0; 326 public ulong XferID = 0;
246 327 public bool isDeleted = false;
247 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) 328
329 private object myLock = new object();
330 private double lastsendTimeMS;
331 private int LastPacket;
332 private int lastBytes;
333 private int lastSentPacket;
334 private int lastAckPacket;
335 private int burstSize;
336 private int retries = 0;
337
338 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client, int burstsz)
248 { 339 {
249 FileName = fileName; 340 FileName = fileName;
250 Data = data; 341 Data = data;
251 XferID = xferID; 342 XferID = xferID;
252 Client = client; 343 Client = client;
344 burstSize = burstsz;
253 } 345 }
254 346
255 public XferDownLoad() 347 public XferDownLoad()
256 { 348 {
257 } 349 }
258 350
351 public void done()
352 {
353 if(!isDeleted)
354 {
355 Data = new byte[0];
356 isDeleted = true;
357 }
358 }
359
259 /// <summary> 360 /// <summary>
260 /// Start a transfer 361 /// Start a transfer
261 /// </summary> 362 /// </summary>
262 /// <returns>True if the transfer is complete, false if not</returns> 363 /// <returns>True if the transfer is complete, false if not</returns>
263 public bool StartSend() 364 public void StartSend()
264 { 365 {
265 if (Data.Length < 1000) 366 lock(myLock)
266 { 367 {
267 // for now (testing) we only support files under 1000 bytes 368 if(Data.Length == 0) //??
268 byte[] transferData = new byte[Data.Length + 4]; 369 {
269 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 370 LastPacket = 0;
270 Array.Copy(Data, 0, transferData, 4, Data.Length); 371 lastBytes = 0;
271 Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); 372 burstSize = 0;
272 complete = true; 373 }
374 else
375 {
376 // payload of 1024bytes
377 LastPacket = Data.Length >> 10;
378 lastBytes = Data.Length & 0x3ff;
379 if(lastBytes == 0)
380 {
381 lastBytes = 1024;
382 LastPacket--;
383 }
384
385 }
386
387 lastAckPacket = -1;
388 lastSentPacket = -1;
389
390 double now = Util.GetTimeStampMS();
391
392 SendBurst(now);
393 return;
394 }
395 }
396
397 private void SendBurst(double now)
398 {
399 int start = lastAckPacket + 1;
400 int end = start + burstSize;
401 if (end > LastPacket)
402 end = LastPacket;
403 while(start <= end)
404 SendPacket(start++ , now);
405 }
406
407 private void SendPacket(int pkt, double now)
408 {
409 if(pkt > LastPacket)
410 return;
411
412 int pktsize;
413 uint pktid;
414 if (pkt == LastPacket)
415 {
416 pktsize = lastBytes;
417 pktid = (uint)pkt | 0x80000000u;
273 } 418 }
274 else 419 else
275 { 420 {
276 byte[] transferData = new byte[1000 + 4]; 421 pktsize = 1024;
422 pktid = (uint)pkt;
423 }
424
425 byte[] transferData;
426 if(pkt == 0)
427 {
428 transferData = new byte[pktsize + 4];
277 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 429 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4);
278 Array.Copy(Data, 0, transferData, 4, 1000); 430 Array.Copy(Data, 0, transferData, 4, pktsize);
279 Client.SendXferPacket(XferID, 0, transferData);
280 Packet++;
281 DataPointer = 1000;
282 } 431 }
432 else
433 {
434 transferData = new byte[pktsize];
435 Array.Copy(Data, pkt << 10, transferData, 0, pktsize);
436 }
437
438 Client.SendXferPacket(XferID, pktid, transferData, false);
283 439
284 return complete; 440 lastSentPacket = pkt;
441 lastsendTimeMS = now;
285 } 442 }
286 443
287 /// <summary> 444 /// <summary>
@@ -291,30 +448,46 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
291 /// <returns>True if the transfer is complete, false otherwise</returns> 448 /// <returns>True if the transfer is complete, false otherwise</returns>
292 public bool AckPacket(uint packet) 449 public bool AckPacket(uint packet)
293 { 450 {
294 if (!complete) 451 lock(myLock)
295 { 452 {
296 if ((Data.Length - DataPointer) > 1000) 453 if(isDeleted)
454 return true;
455
456 packet &= 0x7fffffff;
457 if(lastAckPacket < packet)
458 lastAckPacket = (int)packet;
459
460 if(lastAckPacket == LastPacket)
297 { 461 {
298 byte[] transferData = new byte[1000]; 462 done();
299 Array.Copy(Data, DataPointer, transferData, 0, 1000); 463 return true;
300 Client.SendXferPacket(XferID, Packet, transferData);
301 Packet++;
302 DataPointer += 1000;
303 } 464 }
304 else 465 double now = Util.GetTimeStampMS();
466 SendPacket(lastSentPacket + 1, now);
467 return false;
468 }
469 }
470
471 public bool checkTime(double now)
472 {
473 if(Monitor.TryEnter(myLock))
474 {
475 if(!isDeleted)
305 { 476 {
306 byte[] transferData = new byte[Data.Length - DataPointer]; 477 double timeMS = now - lastsendTimeMS;
307 Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); 478 if(timeMS > 60000.0)
308 uint endPacket = Packet |= (uint) 0x80000000; 479 done();
309 Client.SendXferPacket(XferID, endPacket, transferData); 480 else if(timeMS > 3500.0 && retries++ < 3)
310 Packet++; 481 {
311 DataPointer += (Data.Length - DataPointer); 482 burstSize >>= 1;
312 483 SendBurst(now);
313 complete = true; 484 }
314 } 485 }
315 }
316 486
317 return complete; 487 Monitor.Exit(myLock);
488 return isDeleted;
489 }
490 return false;
318 } 491 }
319 } 492 }
320 493
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
index ebec9d2..403236c 100644
--- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -41,16 +41,16 @@ namespace OpenSim.Region.CoreModules.Asset
41 /// </summary> 41 /// </summary>
42 /// <remarks> 42 /// <remarks>
43 /// <para> 43 /// <para>
44 /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache". 44 /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache".
45 /// When cache is successfully enable log should have message 45 /// When cache is successfully enable log should have message
46 /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)". 46 /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)".
47 /// </para> 47 /// </para>
48 /// <para> 48 /// <para>
49 /// Cache's size is limited by two parameters: 49 /// Cache's size is limited by two parameters:
50 /// maximal allowed size in bytes and maximal allowed asset count. When new asset 50 /// maximal allowed size in bytes and maximal allowed asset count. When new asset
51 /// is added to cache that have achieved either size or count limitation, cache 51 /// is added to cache that have achieved either size or count limitation, cache
52 /// will automatically remove less recently used assets from cache. Additionally 52 /// will automatically remove less recently used assets from cache. Additionally
53 /// asset's lifetime is controlled by expiration time. 53 /// asset's lifetime is controlled by expiration time.
54 /// </para> 54 /// </para>
55 /// <para> 55 /// <para>
56 /// <list type="table"> 56 /// <list type="table">
@@ -91,10 +91,10 @@ namespace OpenSim.Region.CoreModules.Asset
91 /// </code> 91 /// </code>
92 /// </example> 92 /// </example>
93 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CenomeMemoryAssetCache")] 93 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CenomeMemoryAssetCache")]
94 public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule 94 public class CenomeMemoryAssetCache : IAssetCache, ISharedRegionModule
95 { 95 {
96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
97 97
98 /// <summary> 98 /// <summary>
99 /// Cache's default maximal asset count. 99 /// Cache's default maximal asset count.
100 /// </summary> 100 /// </summary>
@@ -119,7 +119,7 @@ namespace OpenSim.Region.CoreModules.Asset
119 /// Asset's default expiration time in the cache. 119 /// Asset's default expiration time in the cache.
120 /// </summary> 120 /// </summary>
121 public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes(30.0); 121 public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes(30.0);
122 122
123 /// <summary> 123 /// <summary>
124 /// Cache object. 124 /// Cache object.
125 /// </summary> 125 /// </summary>
@@ -192,7 +192,7 @@ namespace OpenSim.Region.CoreModules.Asset
192 expirationTime); 192 expirationTime);
193 } 193 }
194 194
195 #region IImprovedAssetCache Members 195 #region IAssetCache Members
196 196
197 public bool Check(string id) 197 public bool Check(string id)
198 { 198 {
@@ -213,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Asset
213 if (asset != null) 213 if (asset != null)
214 { 214 {
215// m_log.DebugFormat("[CENOME ASSET CACHE]: Caching asset {0}", asset.ID); 215// m_log.DebugFormat("[CENOME ASSET CACHE]: Caching asset {0}", asset.ID);
216 216
217 long size = asset.Data != null ? asset.Data.Length : 1; 217 long size = asset.Data != null ? asset.Data.Length : 1;
218 m_cache.Set(asset.ID, asset, size); 218 m_cache.Set(asset.ID, asset, size);
219 m_cachedCount++; 219 m_cachedCount++;
@@ -221,6 +221,11 @@ namespace OpenSim.Region.CoreModules.Asset
221 221
222 } 222 }
223 223
224 public void CacheNegative(string id)
225 {
226 // We don't do negative caching
227 }
228
224 /// <summary> 229 /// <summary>
225 /// Clear asset cache. 230 /// Clear asset cache.
226 /// </summary> 231 /// </summary>
@@ -241,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Asset
241 } 246 }
242 247
243 /// <summary> 248 /// <summary>
244 /// Get asset stored 249 /// Get asset stored
245 /// </summary> 250 /// </summary>
246 /// <param name="id"> 251 /// <param name="id">
247 /// The asset's id. 252 /// The asset's id.
@@ -255,10 +260,9 @@ namespace OpenSim.Region.CoreModules.Asset
255 /// Cache doesn't guarantee in any situation that asset is stored to it. 260 /// Cache doesn't guarantee in any situation that asset is stored to it.
256 /// </para> 261 /// </para>
257 /// </remarks> 262 /// </remarks>
258 public AssetBase Get(string id) 263 public bool Get(string id, out AssetBase assetBase)
259 { 264 {
260 m_getCount++; 265 m_getCount++;
261 AssetBase assetBase;
262 if (m_cache.TryGetValue(id, out assetBase)) 266 if (m_cache.TryGetValue(id, out assetBase))
263 m_hitCount++; 267 m_hitCount++;
264 268
@@ -278,8 +282,8 @@ namespace OpenSim.Region.CoreModules.Asset
278 282
279// if (null == assetBase) 283// if (null == assetBase)
280// m_log.DebugFormat("[CENOME ASSET CACHE]: Asset {0} not in cache", id); 284// m_log.DebugFormat("[CENOME ASSET CACHE]: Asset {0} not in cache", id);
281 285
282 return assetBase; 286 return true;
283 } 287 }
284 288
285 #endregion 289 #endregion
@@ -294,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Asset
294 get { return "CenomeMemoryAssetCache"; } 298 get { return "CenomeMemoryAssetCache"; }
295 } 299 }
296 300
297 public Type ReplaceableInterface 301 public Type ReplaceableInterface
298 { 302 {
299 get { return null; } 303 get { return null; }
300 } 304 }
@@ -308,7 +312,7 @@ namespace OpenSim.Region.CoreModules.Asset
308 public void AddRegion(Scene scene) 312 public void AddRegion(Scene scene)
309 { 313 {
310 if (m_enabled) 314 if (m_enabled)
311 scene.RegisterModuleInterface<IImprovedAssetCache>(this); 315 scene.RegisterModuleInterface<IAssetCache>(this);
312 } 316 }
313 317
314 /// <summary> 318 /// <summary>
@@ -344,7 +348,7 @@ namespace OpenSim.Region.CoreModules.Asset
344 348
345 if (name != Name) 349 if (name != Name)
346 return; 350 return;
347 351
348 long maxSize = DefaultMaxSize; 352 long maxSize = DefaultMaxSize;
349 int maxCount = DefaultMaxCount; 353 int maxCount = DefaultMaxCount;
350 TimeSpan expirationTime = DefaultExpirationTime; 354 TimeSpan expirationTime = DefaultExpirationTime;
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
index f720748..10c0e85 100644
--- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
@@ -40,7 +40,7 @@ using OpenSim.Services.Interfaces;
40namespace OpenSim.Region.CoreModules.Asset 40namespace OpenSim.Region.CoreModules.Asset
41{ 41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CoreAssetCache")] 42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CoreAssetCache")]
43 public class CoreAssetCache : ISharedRegionModule, IImprovedAssetCache 43 public class CoreAssetCache : ISharedRegionModule, IAssetCache
44 { 44 {
45 private static readonly ILog m_log = 45 private static readonly ILog m_log =
46 LogManager.GetLogger( 46 LogManager.GetLogger(
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Asset
54 get { return "CoreAssetCache"; } 54 get { return "CoreAssetCache"; }
55 } 55 }
56 56
57 public Type ReplaceableInterface 57 public Type ReplaceableInterface
58 { 58 {
59 get { return null; } 59 get { return null; }
60 } 60 }
@@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Asset
98 public void AddRegion(Scene scene) 98 public void AddRegion(Scene scene)
99 { 99 {
100 if (m_Enabled) 100 if (m_Enabled)
101 scene.RegisterModuleInterface<IImprovedAssetCache>(this); 101 scene.RegisterModuleInterface<IAssetCache>(this);
102 } 102 }
103 103
104 public void RemoveRegion(Scene scene) 104 public void RemoveRegion(Scene scene)
@@ -110,12 +110,15 @@ namespace OpenSim.Region.CoreModules.Asset
110 } 110 }
111 111
112 //////////////////////////////////////////////////////////// 112 ////////////////////////////////////////////////////////////
113 // IImprovedAssetCache 113 // IAssetCache
114 // 114 //
115 public bool Check(string id) 115 public bool Check(string id)
116 { 116 {
117 // XXX This is probably not an efficient implementation. 117 // XXX This is probably not an efficient implementation.
118 return Get(id) != null; 118 AssetBase asset;
119 if (!Get(id, out asset))
120 return false;
121 return asset != null;
119 } 122 }
120 123
121 public void Cache(AssetBase asset) 124 public void Cache(AssetBase asset)
@@ -124,9 +127,15 @@ namespace OpenSim.Region.CoreModules.Asset
124 m_Cache.Store(asset.ID, asset); 127 m_Cache.Store(asset.ID, asset);
125 } 128 }
126 129
127 public AssetBase Get(string id) 130 public void CacheNegative(string id)
128 { 131 {
129 return (AssetBase)m_Cache.Get(id); 132 // We don't do negative caching
133 }
134
135 public bool Get(string id, out AssetBase asset)
136 {
137 asset = (AssetBase)m_Cache.Get(id);
138 return true;
130 } 139 }
131 140
132 public void Expire(string id) 141 public void Expire(string id)
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 17646fb..bb0f424 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -25,7 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28// Uncomment to make asset Get requests for existing 28// Uncomment to make asset Get requests for existing
29// #define WAIT_ON_INPROGRESS_REQUESTS 29// #define WAIT_ON_INPROGRESS_REQUESTS
30 30
31using System; 31using System;
@@ -55,16 +55,18 @@ using OpenSim.Services.Interfaces;
55namespace OpenSim.Region.CoreModules.Asset 55namespace OpenSim.Region.CoreModules.Asset
56{ 56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FlotsamAssetCache")] 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FlotsamAssetCache")]
58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService 58 public class FlotsamAssetCache : ISharedRegionModule, IAssetCache, IAssetService
59 { 59 {
60 private static readonly ILog m_log = 60 private static readonly ILog m_log =
61 LogManager.GetLogger( 61 LogManager.GetLogger(
62 MethodBase.GetCurrentMethod().DeclaringType); 62 MethodBase.GetCurrentMethod().DeclaringType);
63 63
64 private bool m_Enabled; 64 private bool m_Enabled;
65 private bool m_timerRunning;
66 private bool m_cleanupRunning;
65 67
66 private const string m_ModuleName = "FlotsamAssetCache"; 68 private const string m_ModuleName = "FlotsamAssetCache";
67 private const string m_DefaultCacheDirectory = "../caches/assetcache"; 69 private const string m_DefaultCacheDirectory = "assetcache";
68 private string m_CacheDirectory = m_DefaultCacheDirectory; 70 private string m_CacheDirectory = m_DefaultCacheDirectory;
69 71
70 private readonly List<char> m_InvalidChars = new List<char>(); 72 private readonly List<char> m_InvalidChars = new List<char>();
@@ -76,6 +78,7 @@ namespace OpenSim.Region.CoreModules.Asset
76 private static ulong m_RequestsForInprogress; 78 private static ulong m_RequestsForInprogress;
77 private static ulong m_DiskHits; 79 private static ulong m_DiskHits;
78 private static ulong m_MemoryHits; 80 private static ulong m_MemoryHits;
81 private static ulong m_weakRefHits;
79 82
80#if WAIT_ON_INPROGRESS_REQUESTS 83#if WAIT_ON_INPROGRESS_REQUESTS
81 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>(); 84 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>();
@@ -89,12 +92,17 @@ namespace OpenSim.Region.CoreModules.Asset
89 private ExpiringCache<string, AssetBase> m_MemoryCache; 92 private ExpiringCache<string, AssetBase> m_MemoryCache;
90 private bool m_MemoryCacheEnabled = false; 93 private bool m_MemoryCacheEnabled = false;
91 94
95 private ExpiringCache<string, object> m_negativeCache;
96 private bool m_negativeCacheEnabled = true;
97 private bool m_negativeCacheSliding = false;
98
92 // Expiration is expressed in hours. 99 // Expiration is expressed in hours.
93 private const double m_DefaultMemoryExpiration = 2; 100 private double m_MemoryExpiration = 0.016;
94 private const double m_DefaultFileExpiration = 48; 101 private const double m_DefaultFileExpiration = 48;
95 private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration); 102 // Negative cache is in seconds
103 private int m_negativeExpiration = 120;
96 private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); 104 private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration);
97 private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(0.166); 105 private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0);
98 106
99 private static int m_CacheDirectoryTiers = 1; 107 private static int m_CacheDirectoryTiers = 1;
100 private static int m_CacheDirectoryTierLen = 3; 108 private static int m_CacheDirectoryTierLen = 3;
@@ -104,6 +112,11 @@ namespace OpenSim.Region.CoreModules.Asset
104 112
105 private IAssetService m_AssetService; 113 private IAssetService m_AssetService;
106 private List<Scene> m_Scenes = new List<Scene>(); 114 private List<Scene> m_Scenes = new List<Scene>();
115 private object timerLock = new object();
116
117 private Dictionary<string,WeakReference> weakAssetReferences = new Dictionary<string, WeakReference>();
118 private object weakAssetReferencesLock = new object();
119 private bool m_updateFileTimeOnCacheHit = false;
107 120
108 public FlotsamAssetCache() 121 public FlotsamAssetCache()
109 { 122 {
@@ -111,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Asset
111 m_InvalidChars.AddRange(Path.GetInvalidFileNameChars()); 124 m_InvalidChars.AddRange(Path.GetInvalidFileNameChars());
112 } 125 }
113 126
114 public Type ReplaceableInterface 127 public Type ReplaceableInterface
115 { 128 {
116 get { return null; } 129 get { return null; }
117 } 130 }
@@ -124,7 +137,7 @@ namespace OpenSim.Region.CoreModules.Asset
124 public void Initialise(IConfigSource source) 137 public void Initialise(IConfigSource source)
125 { 138 {
126 IConfig moduleConfig = source.Configs["Modules"]; 139 IConfig moduleConfig = source.Configs["Modules"];
127 140
128 if (moduleConfig != null) 141 if (moduleConfig != null)
129 { 142 {
130 string name = moduleConfig.GetString("AssetCaching", String.Empty); 143 string name = moduleConfig.GetString("AssetCaching", String.Empty);
@@ -132,6 +145,7 @@ namespace OpenSim.Region.CoreModules.Asset
132 if (name == Name) 145 if (name == Name)
133 { 146 {
134 m_MemoryCache = new ExpiringCache<string, AssetBase>(); 147 m_MemoryCache = new ExpiringCache<string, AssetBase>();
148 m_negativeCache = new ExpiringCache<string, object>();
135 m_Enabled = true; 149 m_Enabled = true;
136 150
137 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name); 151 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name);
@@ -145,15 +159,21 @@ namespace OpenSim.Region.CoreModules.Asset
145 else 159 else
146 { 160 {
147 m_FileCacheEnabled = assetConfig.GetBoolean("FileCacheEnabled", m_FileCacheEnabled); 161 m_FileCacheEnabled = assetConfig.GetBoolean("FileCacheEnabled", m_FileCacheEnabled);
148 m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); 162 m_CacheDirectory = assetConfig.GetString("CacheDirectory", Path.Combine(Util.cacheDir(), m_DefaultCacheDirectory));
149 163
150 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); 164 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
151 m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); 165 m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration);
152 166 m_MemoryExpiration *= 3600.0; // config in hours to seconds
167
168 m_negativeCacheEnabled = assetConfig.GetBoolean("NegativeCacheEnabled", m_negativeCacheEnabled);
169 m_negativeExpiration = assetConfig.GetInt("NegativeCacheTimeout", m_negativeExpiration);
170 m_negativeCacheSliding = assetConfig.GetBoolean("NegativeCacheSliding", m_negativeCacheSliding);
171 m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit);
172
153 #if WAIT_ON_INPROGRESS_REQUESTS 173 #if WAIT_ON_INPROGRESS_REQUESTS
154 m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); 174 m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000);
155 #endif 175 #endif
156 176
157 m_LogLevel = assetConfig.GetInt("LogLevel", m_LogLevel); 177 m_LogLevel = assetConfig.GetInt("LogLevel", m_LogLevel);
158 m_HitRateDisplay = (ulong)assetConfig.GetLong("HitRateDisplay", (long)m_HitRateDisplay); 178 m_HitRateDisplay = (ulong)assetConfig.GetLong("HitRateDisplay", (long)m_HitRateDisplay);
159 179
@@ -170,14 +190,6 @@ namespace OpenSim.Region.CoreModules.Asset
170 190
171 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); 191 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
172 192
173 if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
174 {
175 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
176 m_CacheCleanTimer.AutoReset = true;
177 m_CacheCleanTimer.Elapsed += CleanupExpiredFiles;
178 lock (m_CacheCleanTimer)
179 m_CacheCleanTimer.Start();
180 }
181 193
182 if (m_CacheDirectoryTiers < 1) 194 if (m_CacheDirectoryTiers < 1)
183 { 195 {
@@ -217,9 +229,8 @@ namespace OpenSim.Region.CoreModules.Asset
217 { 229 {
218 if (m_Enabled) 230 if (m_Enabled)
219 { 231 {
220 scene.RegisterModuleInterface<IImprovedAssetCache>(this); 232 scene.RegisterModuleInterface<IAssetCache>(this);
221 m_Scenes.Add(scene); 233 m_Scenes.Add(scene);
222
223 } 234 }
224 } 235 }
225 236
@@ -227,23 +238,61 @@ namespace OpenSim.Region.CoreModules.Asset
227 { 238 {
228 if (m_Enabled) 239 if (m_Enabled)
229 { 240 {
230 scene.UnregisterModuleInterface<IImprovedAssetCache>(this); 241 scene.UnregisterModuleInterface<IAssetCache>(this);
231 m_Scenes.Remove(scene); 242 m_Scenes.Remove(scene);
243 lock(timerLock)
244 {
245 if(m_timerRunning && m_Scenes.Count <= 0)
246 {
247 m_timerRunning = false;
248 m_CacheCleanTimer.Stop();
249 m_CacheCleanTimer.Close();
250 }
251 }
232 } 252 }
233 } 253 }
234 254
235 public void RegionLoaded(Scene scene) 255 public void RegionLoaded(Scene scene)
236 { 256 {
237 if (m_Enabled && m_AssetService == null) 257 if (m_Enabled)
238 m_AssetService = scene.RequestModuleInterface<IAssetService>(); 258 {
259 if(m_AssetService == null)
260 m_AssetService = scene.RequestModuleInterface<IAssetService>();
261 lock(timerLock)
262 {
263 if(!m_timerRunning)
264 {
265 if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
266 {
267 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
268 m_CacheCleanTimer.AutoReset = false;
269 m_CacheCleanTimer.Elapsed += CleanupExpiredFiles;
270 m_CacheCleanTimer.Start();
271 m_timerRunning = true;
272 }
273 }
274 }
275 if (m_MemoryCacheEnabled)
276 m_MemoryCache = new ExpiringCache<string, AssetBase>();
277
278 lock(weakAssetReferencesLock)
279 weakAssetReferences = new Dictionary<string, WeakReference>();
280 }
239 } 281 }
240 282
241 //////////////////////////////////////////////////////////// 283 ////////////////////////////////////////////////////////////
242 // IImprovedAssetCache 284 // IAssetCache
243 // 285 //
286 private void UpdateWeakReference(string key, AssetBase asset)
287 {
288 WeakReference aref = new WeakReference(asset);
289 lock(weakAssetReferencesLock)
290 weakAssetReferences[key] = aref;
291 }
244 292
245 private void UpdateMemoryCache(string key, AssetBase asset) 293 private void UpdateMemoryCache(string key, AssetBase asset)
246 { 294 {
295 // NOTE DO NOT USE SLIDEEXPIRE option on current libomv
247 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); 296 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
248 } 297 }
249 298
@@ -257,11 +306,11 @@ namespace OpenSim.Region.CoreModules.Asset
257 if (File.Exists(filename)) 306 if (File.Exists(filename))
258 { 307 {
259 UpdateFileLastAccessTime(filename); 308 UpdateFileLastAccessTime(filename);
260 } 309 }
261 else 310 else
262 { 311 {
263 // Once we start writing, make sure we flag that we're writing 312 // Once we start writing, make sure we flag that we're writing
264 // that object to the cache so that we don't try to write the 313 // that object to the cache so that we don't try to write the
265 // same file multiple times. 314 // same file multiple times.
266 lock (m_CurrentlyWriting) 315 lock (m_CurrentlyWriting)
267 { 316 {
@@ -306,6 +355,7 @@ namespace OpenSim.Region.CoreModules.Asset
306 if (asset != null) 355 if (asset != null)
307 { 356 {
308 //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); 357 //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
358 UpdateWeakReference(asset.ID, asset);
309 359
310 if (m_MemoryCacheEnabled) 360 if (m_MemoryCacheEnabled)
311 UpdateMemoryCache(asset.ID, asset); 361 UpdateMemoryCache(asset.ID, asset);
@@ -315,6 +365,17 @@ namespace OpenSim.Region.CoreModules.Asset
315 } 365 }
316 } 366 }
317 367
368 public void CacheNegative(string id)
369 {
370 if (m_negativeCacheEnabled)
371 {
372 if (m_negativeCacheSliding)
373 m_negativeCache.AddOrUpdate(id, null, TimeSpan.FromSeconds(m_negativeExpiration));
374 else
375 m_negativeCache.AddOrUpdate(id, null, m_negativeExpiration);
376 }
377 }
378
318 /// <summary> 379 /// <summary>
319 /// Updates the cached file with the current time. 380 /// Updates the cached file with the current time.
320 /// </summary> 381 /// </summary>
@@ -333,6 +394,25 @@ namespace OpenSim.Region.CoreModules.Asset
333 } 394 }
334 } 395 }
335 396
397 private AssetBase GetFromWeakReference(string id)
398 {
399 AssetBase asset = null;
400 WeakReference aref;
401
402 lock(weakAssetReferencesLock)
403 {
404 if (weakAssetReferences.TryGetValue(id, out aref))
405 {
406 asset = aref.Target as AssetBase;
407 if(asset == null)
408 weakAssetReferences.Remove(id);
409 else
410 m_weakRefHits++;
411 }
412 }
413 return asset;
414 }
415
336 /// <summary> 416 /// <summary>
337 /// Try to get an asset from the in-memory cache. 417 /// Try to get an asset from the in-memory cache.
338 /// </summary> 418 /// </summary>
@@ -359,7 +439,7 @@ namespace OpenSim.Region.CoreModules.Asset
359 /// <param name="id"></param> 439 /// <param name="id"></param>
360 /// <returns>An asset retrieved from the file cache. null if there was a problem retrieving an asset.</returns> 440 /// <returns>An asset retrieved from the file cache. null if there was a problem retrieving an asset.</returns>
361 private AssetBase GetFromFileCache(string id) 441 private AssetBase GetFromFileCache(string id)
362 { 442 {
363 string filename = GetFileName(id); 443 string filename = GetFileName(id);
364 444
365#if WAIT_ON_INPROGRESS_REQUESTS 445#if WAIT_ON_INPROGRESS_REQUESTS
@@ -394,6 +474,8 @@ namespace OpenSim.Region.CoreModules.Asset
394 { 474 {
395 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) 475 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
396 { 476 {
477 if (stream.Length == 0) // Empty file will trigger exception below
478 return null;
397 BinaryFormatter bformatter = new BinaryFormatter(); 479 BinaryFormatter bformatter = new BinaryFormatter();
398 480
399 asset = (AssetBase)bformatter.Deserialize(stream); 481 asset = (AssetBase)bformatter.Deserialize(stream);
@@ -451,23 +533,57 @@ namespace OpenSim.Region.CoreModules.Asset
451 return found; 533 return found;
452 } 534 }
453 535
536 // For IAssetService
454 public AssetBase Get(string id) 537 public AssetBase Get(string id)
455 { 538 {
539 AssetBase asset;
540 Get(id, out asset);
541 return asset;
542 }
543
544 public bool Get(string id, out AssetBase asset)
545 {
546 asset = null;
547
456 m_Requests++; 548 m_Requests++;
457 549
458 AssetBase asset = null; 550 object dummy;
551 if (m_negativeCache.TryGetValue(id, out dummy))
552 {
553 return false;
554 }
459 555
460 if (m_MemoryCacheEnabled) 556 asset = GetFromWeakReference(id);
557 if (asset != null && m_updateFileTimeOnCacheHit)
558 {
559 string filename = GetFileName(id);
560 UpdateFileLastAccessTime(filename);
561 }
562
563 if (m_MemoryCacheEnabled && asset == null)
564 {
461 asset = GetFromMemoryCache(id); 565 asset = GetFromMemoryCache(id);
566 if(asset != null)
567 {
568 UpdateWeakReference(id,asset);
569 if (m_updateFileTimeOnCacheHit)
570 {
571 string filename = GetFileName(id);
572 UpdateFileLastAccessTime(filename);
573 }
574 }
575 }
462 576
463 if (asset == null && m_FileCacheEnabled) 577 if (asset == null && m_FileCacheEnabled)
464 { 578 {
465 asset = GetFromFileCache(id); 579 asset = GetFromFileCache(id);
466 580 if(asset != null)
467 if (m_MemoryCacheEnabled && asset != null) 581 UpdateWeakReference(id,asset);
468 UpdateMemoryCache(id, asset);
469 } 582 }
470 583
584 if (m_MemoryCacheEnabled && asset != null)
585 UpdateMemoryCache(id, asset);
586
471 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 587 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
472 { 588 {
473 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); 589 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit");
@@ -475,7 +591,7 @@ namespace OpenSim.Region.CoreModules.Asset
475 GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l)); 591 GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l));
476 } 592 }
477 593
478 return asset; 594 return true;
479 } 595 }
480 596
481 public bool Check(string id) 597 public bool Check(string id)
@@ -490,7 +606,9 @@ namespace OpenSim.Region.CoreModules.Asset
490 606
491 public AssetBase GetCached(string id) 607 public AssetBase GetCached(string id)
492 { 608 {
493 return Get(id); 609 AssetBase asset;
610 Get(id, out asset);
611 return asset;
494 } 612 }
495 613
496 public void Expire(string id) 614 public void Expire(string id)
@@ -511,6 +629,9 @@ namespace OpenSim.Region.CoreModules.Asset
511 629
512 if (m_MemoryCacheEnabled) 630 if (m_MemoryCacheEnabled)
513 m_MemoryCache.Remove(id); 631 m_MemoryCache.Remove(id);
632
633 lock(weakAssetReferencesLock)
634 weakAssetReferences.Remove(id);
514 } 635 }
515 catch (Exception e) 636 catch (Exception e)
516 { 637 {
@@ -525,7 +646,7 @@ namespace OpenSim.Region.CoreModules.Asset
525 if (m_LogLevel >= 2) 646 if (m_LogLevel >= 2)
526 m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches."); 647 m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches.");
527 648
528 if (m_FileCacheEnabled) 649 if (m_FileCacheEnabled && Directory.Exists(m_CacheDirectory))
529 { 650 {
530 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 651 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
531 { 652 {
@@ -534,7 +655,12 @@ namespace OpenSim.Region.CoreModules.Asset
534 } 655 }
535 656
536 if (m_MemoryCacheEnabled) 657 if (m_MemoryCacheEnabled)
537 m_MemoryCache.Clear(); 658 m_MemoryCache = new ExpiringCache<string, AssetBase>();
659 if (m_negativeCacheEnabled)
660 m_negativeCache = new ExpiringCache<string, object>();
661
662 lock(weakAssetReferencesLock)
663 weakAssetReferences = new Dictionary<string, WeakReference>();
538 } 664 }
539 665
540 private void CleanupExpiredFiles(object source, ElapsedEventArgs e) 666 private void CleanupExpiredFiles(object source, ElapsedEventArgs e)
@@ -542,6 +668,12 @@ namespace OpenSim.Region.CoreModules.Asset
542 if (m_LogLevel >= 2) 668 if (m_LogLevel >= 2)
543 m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration); 669 m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration);
544 670
671 lock(timerLock)
672 {
673 if(!m_timerRunning || m_cleanupRunning)
674 return;
675 m_cleanupRunning = true;
676 }
545 // Purge all files last accessed prior to this point 677 // Purge all files last accessed prior to this point
546 DateTime purgeLine = DateTime.Now - m_FileExpiration; 678 DateTime purgeLine = DateTime.Now - m_FileExpiration;
547 679
@@ -549,27 +681,34 @@ namespace OpenSim.Region.CoreModules.Asset
549 // before cleaning up expired files we must scan the objects in the scene to make sure that we retain 681 // before cleaning up expired files we must scan the objects in the scene to make sure that we retain
550 // such local assets if they have not been recently accessed. 682 // such local assets if they have not been recently accessed.
551 TouchAllSceneAssets(false); 683 TouchAllSceneAssets(false);
684 if(Directory.Exists(m_CacheDirectory))
685 {
686 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
687 CleanExpiredFiles(dir, purgeLine);
688 }
552 689
553 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 690 lock(timerLock)
554 { 691 {
555 CleanExpiredFiles(dir, purgeLine); 692 if(m_timerRunning)
693 m_CacheCleanTimer.Start();
694 m_cleanupRunning = false;
556 } 695 }
557 } 696 }
558 697
559 /// <summary> 698 /// <summary>
560 /// Recurses through specified directory checking for asset files last 699 /// Recurses through specified directory checking for asset files last
561 /// accessed prior to the specified purge line and deletes them. Also 700 /// accessed prior to the specified purge line and deletes them. Also
562 /// removes empty tier directories. 701 /// removes empty tier directories.
563 /// </summary> 702 /// </summary>
564 /// <param name="dir"></param> 703 /// <param name="dir"></param>
565 /// <param name="purgeLine"></param> 704 /// <param name="purgeLine"></param>
566 private void CleanExpiredFiles(string dir, DateTime purgeLine) 705 private void CleanExpiredFiles(string dir, DateTime purgeLine)
567 { 706 {
568 // Yet another "directory we are trying to remove doesn't exist, so don't complain" idiocy fix.
569 if (!Directory.Exists(dir))
570 return;
571 try 707 try
572 { 708 {
709 if(!Directory.Exists(dir))
710 return;
711
573 foreach (string file in Directory.GetFiles(dir)) 712 foreach (string file in Directory.GetFiles(dir))
574 { 713 {
575 if (File.GetLastAccessTime(file) < purgeLine) 714 if (File.GetLastAccessTime(file) < purgeLine)
@@ -593,14 +732,19 @@ namespace OpenSim.Region.CoreModules.Asset
593 else if (dirSize >= m_CacheWarnAt) 732 else if (dirSize >= m_CacheWarnAt)
594 { 733 {
595 m_log.WarnFormat( 734 m_log.WarnFormat(
596 "[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", 735 "[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration",
597 dir, dirSize); 736 dir, dirSize);
598 } 737 }
599 } 738 }
739 catch (DirectoryNotFoundException)
740 {
741 // If we get here, another node on the same box has
742 // already removed the directory. Continue with next.
743 }
600 catch (Exception e) 744 catch (Exception e)
601 { 745 {
602//// TODO - I'm almost sure this is another case of failing to delete something that doesn't actually exist. 746 m_log.Warn(
603//// m_log.Warn(string.Format("[FLOTSAM ASSET CACHE]: Could not complete clean of expired files in {0}", dir)); 747 string.Format("[FLOTSAM ASSET CACHE]: Could not complete clean of expired files in {0}, exception ", dir), e);
604 } 748 }
605 } 749 }
606 750
@@ -628,7 +772,7 @@ namespace OpenSim.Region.CoreModules.Asset
628 } 772 }
629 773
630 /// <summary> 774 /// <summary>
631 /// Writes a file to the file cache, creating any nessesary 775 /// Writes a file to the file cache, creating any nessesary
632 /// tier directories along the way 776 /// tier directories along the way
633 /// </summary> 777 /// </summary>
634 /// <param name="filename"></param> 778 /// <param name="filename"></param>
@@ -640,7 +784,7 @@ namespace OpenSim.Region.CoreModules.Asset
640 // Make sure the target cache directory exists 784 // Make sure the target cache directory exists
641 string directory = Path.GetDirectoryName(filename); 785 string directory = Path.GetDirectoryName(filename);
642 786
643 // Write file first to a temp name, so that it doesn't look 787 // Write file first to a temp name, so that it doesn't look
644 // like it's already cached while it's still writing. 788 // like it's already cached while it's still writing.
645 string tempname = Path.Combine(directory, Path.GetRandomFileName()); 789 string tempname = Path.Combine(directory, Path.GetRandomFileName());
646 790
@@ -652,7 +796,7 @@ namespace OpenSim.Region.CoreModules.Asset
652 { 796 {
653 Directory.CreateDirectory(directory); 797 Directory.CreateDirectory(directory);
654 } 798 }
655 799
656 stream = File.Open(tempname, FileMode.Create); 800 stream = File.Open(tempname, FileMode.Create);
657 BinaryFormatter bformatter = new BinaryFormatter(); 801 BinaryFormatter bformatter = new BinaryFormatter();
658 bformatter.Serialize(stream, asset); 802 bformatter.Serialize(stream, asset);
@@ -665,6 +809,9 @@ namespace OpenSim.Region.CoreModules.Asset
665 809
666 return; 810 return;
667 } 811 }
812 catch (UnauthorizedAccessException)
813 {
814 }
668 finally 815 finally
669 { 816 {
670 if (stream != null) 817 if (stream != null)
@@ -686,7 +833,7 @@ namespace OpenSim.Region.CoreModules.Asset
686 // This situation occurs fairly rarely anyway. We assume in this that moves are atomic on the 833 // This situation occurs fairly rarely anyway. We assume in this that moves are atomic on the
687 // filesystem. 834 // filesystem.
688 File.Move(tempname, filename); 835 File.Move(tempname, filename);
689 836
690 if (m_LogLevel >= 2) 837 if (m_LogLevel >= 2)
691 m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Cache Stored :: {0}", asset.ID); 838 m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Cache Stored :: {0}", asset.ID);
692 } 839 }
@@ -725,6 +872,9 @@ namespace OpenSim.Region.CoreModules.Asset
725 /// <returns></returns> 872 /// <returns></returns>
726 private int GetFileCacheCount(string dir) 873 private int GetFileCacheCount(string dir)
727 { 874 {
875 if(!Directory.Exists(dir))
876 return 0;
877
728 int count = Directory.GetFiles(dir).Length; 878 int count = Directory.GetFiles(dir).Length;
729 879
730 foreach (string subdir in Directory.GetDirectories(dir)) 880 foreach (string subdir in Directory.GetDirectories(dir))
@@ -743,7 +893,7 @@ namespace OpenSim.Region.CoreModules.Asset
743 { 893 {
744 string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + regionID.ToString() + ".fac"); 894 string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + regionID.ToString() + ".fac");
745 895
746 try 896 try
747 { 897 {
748 if (File.Exists(RegionCacheStatusFile)) 898 if (File.Exists(RegionCacheStatusFile))
749 { 899 {
@@ -752,7 +902,7 @@ namespace OpenSim.Region.CoreModules.Asset
752 else 902 else
753 { 903 {
754 File.WriteAllText( 904 File.WriteAllText(
755 RegionCacheStatusFile, 905 RegionCacheStatusFile,
756 "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache."); 906 "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache.");
757 } 907 }
758 } 908 }
@@ -760,14 +910,14 @@ namespace OpenSim.Region.CoreModules.Asset
760 { 910 {
761 m_log.Warn( 911 m_log.Warn(
762 string.Format( 912 string.Format(
763 "[FLOTSAM ASSET CACHE]: Could not stamp region status file for region {0}. Exception ", 913 "[FLOTSAM ASSET CACHE]: Could not stamp region status file for region {0}. Exception ",
764 regionID), 914 regionID),
765 e); 915 e);
766 } 916 }
767 } 917 }
768 918
769 /// <summary> 919 /// <summary>
770 /// Iterates through all Scenes, doing a deep scan through assets 920 /// Iterates through all Scenes, doing a deep scan through assets
771 /// to update the access time of all assets present in the scene or referenced by assets 921 /// to update the access time of all assets present in the scene or referenced by assets
772 /// in the scene. 922 /// in the scene.
773 /// </summary> 923 /// </summary>
@@ -786,10 +936,16 @@ namespace OpenSim.Region.CoreModules.Asset
786 StampRegionStatusFile(s.RegionInfo.RegionID); 936 StampRegionStatusFile(s.RegionInfo.RegionID);
787 937
788 s.ForEachSOG(delegate(SceneObjectGroup e) 938 s.ForEachSOG(delegate(SceneObjectGroup e)
789 { 939 {
940 if(!m_timerRunning && !storeUncached)
941 return;
942
790 gatherer.AddForInspection(e); 943 gatherer.AddForInspection(e);
791 gatherer.GatherAll(); 944 gatherer.GatherAll();
792 945
946 if(!m_timerRunning && !storeUncached)
947 return;
948
793 foreach (UUID assetID in gatherer.GatheredUuids.Keys) 949 foreach (UUID assetID in gatherer.GatheredUuids.Keys)
794 { 950 {
795 if (!assetsFound.ContainsKey(assetID)) 951 if (!assetsFound.ContainsKey(assetID))
@@ -799,6 +955,7 @@ namespace OpenSim.Region.CoreModules.Asset
799 if (File.Exists(filename)) 955 if (File.Exists(filename))
800 { 956 {
801 UpdateFileLastAccessTime(filename); 957 UpdateFileLastAccessTime(filename);
958 assetsFound[assetID] = true;
802 } 959 }
803 else if (storeUncached) 960 else if (storeUncached)
804 { 961 {
@@ -818,7 +975,14 @@ namespace OpenSim.Region.CoreModules.Asset
818 } 975 }
819 976
820 gatherer.GatheredUuids.Clear(); 977 gatherer.GatheredUuids.Clear();
978 if(!m_timerRunning && !storeUncached)
979 return;
980
981 if(!storeUncached)
982 Thread.Sleep(50);
821 }); 983 });
984 if(!m_timerRunning && !storeUncached)
985 break;
822 } 986 }
823 987
824 return assetsFound.Count; 988 return assetsFound.Count;
@@ -829,6 +993,9 @@ namespace OpenSim.Region.CoreModules.Asset
829 /// </summary> 993 /// </summary>
830 private void ClearFileCache() 994 private void ClearFileCache()
831 { 995 {
996 if(!Directory.Exists(m_CacheDirectory))
997 return;
998
832 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 999 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
833 { 1000 {
834 try 1001 try
@@ -862,22 +1029,35 @@ namespace OpenSim.Region.CoreModules.Asset
862 { 1029 {
863 List<string> outputLines = new List<string>(); 1030 List<string> outputLines = new List<string>();
864 1031
865 double fileHitRate = (double)m_DiskHits / m_Requests * 100.0; 1032 double invReq = 100.0 / m_Requests;
1033
1034 double weakHitRate = m_weakRefHits * invReq;
1035 int weakEntries = weakAssetReferences.Count;
1036
1037 double fileHitRate = m_DiskHits * invReq;
1038 double TotalHitRate = weakHitRate + fileHitRate;
1039
1040 outputLines.Add(
1041 string.Format("Total requests: {0}", m_Requests));
866 outputLines.Add( 1042 outputLines.Add(
867 string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests)); 1043 string.Format("unCollected Hit Rate: {0}% ({1} entries)", weakHitRate.ToString("0.00"),weakEntries));
1044 outputLines.Add(
1045 string.Format("File Hit Rate: {0}%", fileHitRate.ToString("0.00")));
868 1046
869 if (m_MemoryCacheEnabled) 1047 if (m_MemoryCacheEnabled)
870 { 1048 {
871 double memHitRate = (double)m_MemoryHits / m_Requests * 100.0; 1049 double HitRate = m_MemoryHits * invReq;
872
873 outputLines.Add( 1050 outputLines.Add(
874 string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests)); 1051 string.Format("Memory Hit Rate: {0}%", HitRate.ToString("0.00")));
1052
1053 TotalHitRate += HitRate;
875 } 1054 }
1055 outputLines.Add(
1056 string.Format("Total Hit Rate: {0}%", TotalHitRate.ToString("0.00")));
876 1057
877 outputLines.Add( 1058 outputLines.Add(
878 string.Format( 1059 string.Format(
879 "Unnecessary requests due to requests for assets that are currently downloading: {0}", 1060 "Requests overlap during file writing: {0}", m_RequestsForInprogress));
880 m_RequestsForInprogress));
881 1061
882 return outputLines; 1062 return outputLines;
883 } 1063 }
@@ -914,9 +1094,9 @@ namespace OpenSim.Region.CoreModules.Asset
914 if (m_FileCacheEnabled) 1094 if (m_FileCacheEnabled)
915 { 1095 {
916 con.Output("Deep scans have previously been performed on the following regions:"); 1096 con.Output("Deep scans have previously been performed on the following regions:");
917 1097
918 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 1098 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
919 { 1099 {
920 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 1100 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
921 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 1101 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
922 con.OutputFormat("Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 1102 con.OutputFormat("Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
@@ -959,7 +1139,7 @@ namespace OpenSim.Region.CoreModules.Asset
959 con.Output("Memory cache not enabled."); 1139 con.Output("Memory cache not enabled.");
960 } 1140 }
961 } 1141 }
962 1142
963 if (clearFile) 1143 if (clearFile)
964 { 1144 {
965 if (m_FileCacheEnabled) 1145 if (m_FileCacheEnabled)
@@ -976,13 +1156,44 @@ namespace OpenSim.Region.CoreModules.Asset
976 break; 1156 break;
977 1157
978 case "assets": 1158 case "assets":
979 con.Output("Ensuring assets are cached for all scenes."); 1159 lock(timerLock)
1160 {
1161 if(m_cleanupRunning)
1162 {
1163 con.OutputFormat("FloatSam assets check already running");
1164 return;
1165 }
1166 m_cleanupRunning = true;
1167 }
980 1168
981 WorkManager.RunInThread(delegate 1169 con.Output("FloatSam Ensuring assets are cached for all scenes.");
1170
1171 WorkManager.RunInThreadPool(delegate
982 { 1172 {
1173 bool wasRunning= false;
1174 lock(timerLock)
1175 {
1176 if(m_timerRunning)
1177 {
1178 m_CacheCleanTimer.Stop();
1179 m_timerRunning = false;
1180 wasRunning = true;
1181 Thread.Sleep(100);
1182 }
1183 }
983 int assetReferenceTotal = TouchAllSceneAssets(true); 1184 int assetReferenceTotal = TouchAllSceneAssets(true);
1185 GC.Collect();
1186 lock(timerLock)
1187 {
1188 if(wasRunning)
1189 {
1190 m_CacheCleanTimer.Start();
1191 m_timerRunning = true;
1192 }
1193 m_cleanupRunning = false;
1194 }
984 con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal); 1195 con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal);
985 }, null, "TouchAllSceneAssets"); 1196 }, null, "TouchAllSceneAssets", false);
986 1197
987 break; 1198 break;
988 1199
@@ -1037,19 +1248,23 @@ namespace OpenSim.Region.CoreModules.Asset
1037 1248
1038 public AssetMetadata GetMetadata(string id) 1249 public AssetMetadata GetMetadata(string id)
1039 { 1250 {
1040 AssetBase asset = Get(id); 1251 AssetBase asset;
1252 Get(id, out asset);
1041 return asset.Metadata; 1253 return asset.Metadata;
1042 } 1254 }
1043 1255
1044 public byte[] GetData(string id) 1256 public byte[] GetData(string id)
1045 { 1257 {
1046 AssetBase asset = Get(id); 1258 AssetBase asset;
1259 Get(id, out asset);
1047 return asset.Data; 1260 return asset.Data;
1048 } 1261 }
1049 1262
1050 public bool Get(string id, object sender, AssetRetrieved handler) 1263 public bool Get(string id, object sender, AssetRetrieved handler)
1051 { 1264 {
1052 AssetBase asset = Get(id); 1265 AssetBase asset;
1266 if (!Get(id, out asset))
1267 return false;
1053 handler(id, sender, asset); 1268 handler(id, sender, asset);
1054 return true; 1269 return true;
1055 } 1270 }
@@ -1057,12 +1272,12 @@ namespace OpenSim.Region.CoreModules.Asset
1057 public bool[] AssetsExist(string[] ids) 1272 public bool[] AssetsExist(string[] ids)
1058 { 1273 {
1059 bool[] exist = new bool[ids.Length]; 1274 bool[] exist = new bool[ids.Length];
1060 1275
1061 for (int i = 0; i < ids.Length; i++) 1276 for (int i = 0; i < ids.Length; i++)
1062 { 1277 {
1063 exist[i] = Check(ids[i]); 1278 exist[i] = Check(ids[i]);
1064 } 1279 }
1065 1280
1066 return exist; 1281 return exist;
1067 } 1282 }
1068 1283
@@ -1080,7 +1295,9 @@ namespace OpenSim.Region.CoreModules.Asset
1080 1295
1081 public bool UpdateContent(string id, byte[] data) 1296 public bool UpdateContent(string id, byte[] data)
1082 { 1297 {
1083 AssetBase asset = Get(id); 1298 AssetBase asset;
1299 if (!Get(id, out asset))
1300 return false;
1084 asset.Data = data; 1301 asset.Data = data;
1085 Cache(asset); 1302 Cache(asset);
1086 return true; 1303 return true;
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
index 5f76ac2..abe9b23 100644
--- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
@@ -41,7 +41,7 @@ using OpenSim.Services.Interfaces;
41namespace OpenSim.Region.CoreModules.Asset 41namespace OpenSim.Region.CoreModules.Asset
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GlynnTuckerAssetCache")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GlynnTuckerAssetCache")]
44 public class GlynnTuckerAssetCache : ISharedRegionModule, IImprovedAssetCache 44 public class GlynnTuckerAssetCache : ISharedRegionModule, IAssetCache
45 { 45 {
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger( 47 LogManager.GetLogger(
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Asset
55 // Instrumentation 55 // Instrumentation
56 private uint m_DebugRate; 56 private uint m_DebugRate;
57 57
58 public Type ReplaceableInterface 58 public Type ReplaceableInterface
59 { 59 {
60 get { return null; } 60 get { return null; }
61 } 61 }
@@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Asset
100 public void AddRegion(Scene scene) 100 public void AddRegion(Scene scene)
101 { 101 {
102 if (m_Enabled) 102 if (m_Enabled)
103 scene.RegisterModuleInterface<IImprovedAssetCache>(this); 103 scene.RegisterModuleInterface<IAssetCache>(this);
104 } 104 }
105 105
106 public void RemoveRegion(Scene scene) 106 public void RemoveRegion(Scene scene)
@@ -112,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Asset
112 } 112 }
113 113
114 //////////////////////////////////////////////////////////// 114 ////////////////////////////////////////////////////////////
115 // IImprovedAssetCache 115 // IAssetCache
116 // 116 //
117 117
118 public bool Check(string id) 118 public bool Check(string id)
@@ -126,14 +126,20 @@ namespace OpenSim.Region.CoreModules.Asset
126 m_Cache.AddOrUpdate(asset.ID, asset); 126 m_Cache.AddOrUpdate(asset.ID, asset);
127 } 127 }
128 128
129 public AssetBase Get(string id) 129 public void CacheNegative(string id)
130 { 130 {
131 Object asset = null; 131 // We don't do negative caching
132 m_Cache.TryGet(id, out asset); 132 }
133
134 public bool Get(string id, out AssetBase asset)
135 {
136 Object a = null;
137 m_Cache.TryGet(id, out a);
133 138
134 Debug(asset); 139 Debug(a);
135 140
136 return (AssetBase)asset; 141 asset = (AssetBase)a;
142 return true;
137 } 143 }
138 144
139 public void Expire(string id) 145 public void Expire(string id)
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 73e4431..dbb7941 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
112 { 112 {
113 TestHelpers.InMethod(); 113 TestHelpers.InMethod();
114// log4net.Config.XmlConfigurator.Configure(); 114// log4net.Config.XmlConfigurator.Configure();
115 115
116 AssetBase asset = AssetHelpers.CreateNotecardAsset(); 116 AssetBase asset = AssetHelpers.CreateNotecardAsset();
117 asset.ID = TestHelpers.ParseTail(0x2).ToString(); 117 asset.ID = TestHelpers.ParseTail(0x2).ToString();
118 118
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 2f67c4e..f99cf4c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -41,6 +41,8 @@ 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;
45using PermissionMask = OpenSim.Framework.PermissionMask;
44 46
45namespace OpenSim.Region.CoreModules.Avatar.Attachments 47namespace OpenSim.Region.CoreModules.Avatar.Attachments
46{ 48{
@@ -60,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
60 /// A value of 0 will apply no pause. The pause is specified in milliseconds. 62 /// A value of 0 will apply no pause. The pause is specified in milliseconds.
61 /// </remarks> 63 /// </remarks>
62 public int ThrottlePer100PrimsRezzed { get; set; } 64 public int ThrottlePer100PrimsRezzed { get; set; }
63 65
64 private Scene m_scene; 66 private Scene m_scene;
65 private IInventoryAccessModule m_invAccessModule; 67 private IInventoryAccessModule m_invAccessModule;
66 68
@@ -68,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
68 /// Are attachments enabled? 70 /// Are attachments enabled?
69 /// </summary> 71 /// </summary>
70 public bool Enabled { get; private set; } 72 public bool Enabled { get; private set; }
71 73
72 public string Name { get { return "Attachments Module"; } } 74 public string Name { get { return "Attachments Module"; } }
73 public Type ReplaceableInterface { get { return null; } } 75 public Type ReplaceableInterface { get { return null; } }
74 76
@@ -86,14 +88,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
86 Enabled = true; 88 Enabled = true;
87 } 89 }
88 } 90 }
89 91
90 public void AddRegion(Scene scene) 92 public void AddRegion(Scene scene)
91 { 93 {
92 m_scene = scene; 94 m_scene = scene;
93 if (Enabled) 95 if (Enabled)
94 { 96 {
95 // Only register module with scene if it is enabled. All callers check for a null attachments module. 97 // Only register module with scene if it is enabled. All callers check for a null attachments module.
96 // Ideally, there should be a null attachments module for when this core attachments module has been 98 // Ideally, there should be a null attachments module for when this core attachments module has been
97 // disabled. Registering only when enabled allows for other attachments module implementations. 99 // disabled. Registering only when enabled allows for other attachments module implementations.
98 m_scene.RegisterModuleInterface<IAttachmentsModule>(this); 100 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
99 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 101 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
@@ -180,7 +182,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
180 private void HandleScriptStateChange(uint localID, bool started) 182 private void HandleScriptStateChange(uint localID, bool started)
181 { 183 {
182 SceneObjectGroup sog = m_scene.GetGroupByPrim(localID); 184 SceneObjectGroup sog = m_scene.GetGroupByPrim(localID);
183 if (sog != null && sog.IsAttachment) 185 if (sog != null && sog.IsAttachment)
184 { 186 {
185 if (!started) 187 if (!started)
186 { 188 {
@@ -197,21 +199,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
197 } 199 }
198 } 200 }
199 } 201 }
200 202
201 public void RemoveRegion(Scene scene) 203 public void RemoveRegion(Scene scene)
202 { 204 {
203 m_scene.UnregisterModuleInterface<IAttachmentsModule>(this); 205 m_scene.UnregisterModuleInterface<IAttachmentsModule>(this);
204 206
205 if (Enabled) 207 if (Enabled)
206 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 208 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
207 } 209 }
208 210
209 public void RegionLoaded(Scene scene) 211 public void RegionLoaded(Scene scene)
210 { 212 {
211 m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 213 m_invAccessModule = m_scene.RequestModuleInterface<IInventoryAccessModule>();
212 } 214 }
213 215
214 public void Close() 216 public void Close()
215 { 217 {
216 RemoveRegion(m_scene); 218 RemoveRegion(m_scene);
217 } 219 }
@@ -269,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
269 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); 271 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
270 272
271// m_log.DebugFormat( 273// m_log.DebugFormat(
272// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", 274// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}",
273// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name); 275// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name);
274 276
275 so.SetState(ad.AttachmentObjectStates[i++], m_scene); 277 so.SetState(ad.AttachmentObjectStates[i++], m_scene);
@@ -294,7 +296,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
294 { 296 {
295 if (DebugLevel > 0) 297 if (DebugLevel > 0)
296 m_log.DebugFormat( 298 m_log.DebugFormat(
297 "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments", 299 "[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments",
298 m_scene.Name, sp.Name); 300 m_scene.Name, sp.Name);
299 301
300 return; 302 return;
@@ -303,6 +305,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
303 if (DebugLevel > 0) 305 if (DebugLevel > 0)
304 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); 306 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
305 307
308 XmlDocument doc = new XmlDocument();
309 doc.XmlResolver=null;
310 string stateData = String.Empty;
311
312 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
313 if (attServ != null)
314 {
315 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
316 stateData = attServ.Get(sp.UUID.ToString());
317 if (stateData != String.Empty)
318 {
319 try
320 {
321 doc.LoadXml(stateData);
322 }
323 catch { }
324 }
325 }
326
327 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
328
329 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
330 if (nodes.Count > 0)
331 {
332 foreach (XmlNode n in nodes)
333 {
334 XmlElement elem = (XmlElement)n;
335 string itemID = elem.GetAttribute("ItemID");
336 string xml = elem.InnerXml;
337
338 itemData[new UUID(itemID)] = xml;
339 }
340 }
341
342
306 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 343 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
307 344
308 // Let's get all items at once, so they get cached 345 // Let's get all items at once, so they get cached
@@ -322,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
322 359
323 // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down 360 // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
324 // But they're not used anyway, the item is being looked up for now, so let's proceed. 361 // But they're not used anyway, the item is being looked up for now, so let's proceed.
325 //if (UUID.Zero == assetID) 362 //if (UUID.Zero == assetID)
326 //{ 363 //{
327 // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); 364 // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID);
328 // continue; 365 // continue;
@@ -330,10 +367,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
330 367
331 try 368 try
332 { 369 {
370 string xmlData;
371 XmlDocument d = null;
372// UUID asset;
373 if (itemData.TryGetValue(attach.ItemID, out xmlData))
374 {
375 d = new XmlDocument();
376 d.XmlResolver=null;
377 d.LoadXml(xmlData);
378 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
379 }
380
333 // If we're an NPC then skip all the item checks and manipulations since we don't have an 381 // If we're an NPC then skip all the item checks and manipulations since we don't have an
334 // inventory right now. 382 // inventory right now.
335 RezSingleAttachmentFromInventoryInternal( 383 RezSingleAttachmentFromInventoryInternal(
336 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); 384 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
337 } 385 }
338 catch (Exception e) 386 catch (Exception e)
339 { 387 {
@@ -361,26 +409,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
361 409
362 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); 410 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>();
363 411
364 foreach (SceneObjectGroup so in attachments) 412
413 if (sp.PresenceType != PresenceType.Npc)
365 { 414 {
366 // Scripts MUST be snapshotted before the object is 415 foreach (SceneObjectGroup so in attachments)
367 // removed from the scene because doing otherwise will 416 {
368 // clobber the run flag 417 // Scripts MUST be snapshotted before the object is
369 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from 418 // removed from the scene because doing otherwise will
370 // scripts performing attachment operations at the same time. Getting object states stops the scripts. 419 // clobber the run flag
371 scriptStates[so] = PrepareScriptInstanceForSave(so, false); 420 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
421 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
422 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
423 }
372 424
373// m_log.DebugFormat( 425 lock (sp.AttachmentsSyncLock)
374// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}", 426 {
375// so.Name, sp.Name, m_scene.Name, scriptStates[so]); 427 foreach (SceneObjectGroup so in attachments)
428 UpdateDetachedObject(sp, so, scriptStates[so]);
429 sp.ClearAttachments();
430 }
376 } 431 }
377 432 else
378 lock (sp.AttachmentsSyncLock)
379 { 433 {
380 foreach (SceneObjectGroup so in attachments) 434 lock (sp.AttachmentsSyncLock)
381 UpdateDetachedObject(sp, so, scriptStates[so]); 435 {
382 436 foreach (SceneObjectGroup so in attachments)
383 sp.ClearAttachments(); 437 UpdateDetachedObject(sp, so, String.Empty);
438 sp.ClearAttachments();
439 }
384 } 440 }
385 } 441 }
386 442
@@ -392,7 +448,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
392 if (DebugLevel > 0) 448 if (DebugLevel > 0)
393 m_log.DebugFormat( 449 m_log.DebugFormat(
394 "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", 450 "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
395 m_scene.RegionInfo.RegionName, sp.Name, silent); 451 m_scene.RegionInfo.RegionName, sp.Name, silent);
396 452
397 foreach (SceneObjectGroup sop in sp.GetAttachments()) 453 foreach (SceneObjectGroup sop in sp.GetAttachments())
398 { 454 {
@@ -401,21 +457,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
401 457
402 sp.ClearAttachments(); 458 sp.ClearAttachments();
403 } 459 }
404 460
405 public bool AttachObject( 461 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent,
406 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append) 462 bool addToInventory, bool append)
407 { 463 {
408 if (!Enabled) 464 if (!Enabled)
409 return false; 465 return false;
410 466
411 group.DetachFromBackup(); 467 return AttachObjectInternal(sp, group, attachmentPt, silent, 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 } 468 }
420 469
421 /// <summary> 470 /// <summary>
@@ -428,21 +477,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
428 /// <param name='silent'></param> 477 /// <param name='silent'></param>
429 /// <param name='addToInventory'>If true then add object to user inventory.</param> 478 /// <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> 479 /// <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> 480 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt,
432 private bool AttachObjectInternal( 481 bool silent, bool addToInventory, bool resumeScripts, bool append)
433 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append)
434 { 482 {
435 if (group.GetSittingAvatarsCount() != 0) 483// m_log.DebugFormat(
484// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
485// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
486
487
488//// if (group.GetSittingAvatarsCount() != 0)
489//// {
490//// if (DebugLevel > 0)
491//// m_log.WarnFormat(
492//// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
493//// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
494////
495//// return false;
496//// }
497
498 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
499 if (attachments.Contains(group))
436 { 500 {
437 if (DebugLevel > 0) 501// if (DebugLevel > 0)
438 m_log.WarnFormat( 502// m_log.WarnFormat(
439 "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it", 503// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
440 group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount()); 504// group.Name, group.LocalId, sp.Name, attachmentPt);
441 505
442 return false; 506 return false;
443 } 507 }
444 508
445 Vector3 attachPos = group.AbsolutePosition; 509 Vector3 attachPos = group.AbsolutePosition;
510
511 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
512 // be removed when that functionality is implemented in opensim
513 attachmentPt &= 0x7f;
514
446 // If the attachment point isn't the same as the one previously used 515 // 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 516 // set it's offset position = 0 so that it appears on the attachment point
448 // and not in a weird location somewhere unknown. 517 // and not in a weird location somewhere unknown.
@@ -470,7 +539,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
470 { 539 {
471 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; 540 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
472 attachPos = group.RootPart.AttachedPos; 541 attachPos = group.RootPart.AttachedPos;
473 group.HasGroupChanged = true;
474 } 542 }
475 543
476 // if we still didn't find a suitable attachment point....... 544 // if we still didn't find a suitable attachment point.......
@@ -481,21 +549,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
481 attachPos = Vector3.Zero; 549 attachPos = Vector3.Zero;
482 } 550 }
483 551
484 group.AttachmentPoint = attachmentPt;
485 group.AbsolutePosition = attachPos;
486
487 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
488
489 if (attachments.Contains(group))
490 {
491 if (DebugLevel > 0)
492 m_log.WarnFormat(
493 "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
494 group.Name, group.LocalId, sp.Name, attachmentPt);
495
496 return false;
497 }
498
499 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones 552 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
500 while (attachments.Count >= 5) 553 while (attachments.Count >= 5)
501 { 554 {
@@ -514,11 +567,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
514 } 567 }
515 } 568 }
516 569
570 group.DetachFromBackup();
571
517 lock (sp.AttachmentsSyncLock) 572 lock (sp.AttachmentsSyncLock)
518 { 573 {
574 group.AttachmentPoint = attachmentPt;
575 group.RootPart.AttachedPos = attachPos;
576
519 if (addToInventory && sp.PresenceType != PresenceType.Npc) 577 if (addToInventory && sp.PresenceType != PresenceType.Npc)
520 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); 578 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
521 579
522 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 580 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
523 581
524 if (resumeScripts) 582 if (resumeScripts)
@@ -529,8 +587,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
529 group.ResumeScripts(); 587 group.ResumeScripts();
530 } 588 }
531 589
590 else
532 // Do this last so that event listeners have access to all the effects of the attachment 591 // Do this last so that event listeners have access to all the effects of the attachment
533 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); 592 // this can't be done when creating scripts:
593 // scripts do internal enqueue of attach event
594 // and not all scripts are loaded at this point
595 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
534 } 596 }
535 597
536 return true; 598 return true;
@@ -546,7 +608,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
546 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 608 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
547 } 609 }
548 610
549 public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 611 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
612 {
613 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
614 }
615
616 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
550 { 617 {
551 if (!Enabled) 618 if (!Enabled)
552 return null; 619 return null;
@@ -557,8 +624,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
557 (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name); 624 (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
558 625
559 // We check the attachments in the avatar appearance here rather than the objects attached to the 626 // We check the attachments in the avatar appearance here rather than the objects attached to the
560 // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are 627 // ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are
561 // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done 628 // already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done
562 // because pre-outfit folder viewers (most version 1 viewers) require it. 629 // because pre-outfit folder viewers (most version 1 viewers) require it.
563 bool alreadyOn = false; 630 bool alreadyOn = false;
564 List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments(); 631 List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments();
@@ -584,7 +651,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
584 bool append = (AttachmentPt & 0x80) != 0; 651 bool append = (AttachmentPt & 0x80) != 0;
585 AttachmentPt &= 0x7f; 652 AttachmentPt &= 0x7f;
586 653
587 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); 654 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
588 } 655 }
589 656
590 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 657 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -594,7 +661,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
594 661
595 if (DebugLevel > 0) 662 if (DebugLevel > 0)
596 m_log.DebugFormat( 663 m_log.DebugFormat(
597 "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}", 664 "[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}",
598 rezlist.Count, sp.Name, m_scene.Name); 665 rezlist.Count, sp.Name, m_scene.Name);
599 666
600 foreach (KeyValuePair<UUID, uint> rez in rezlist) 667 foreach (KeyValuePair<UUID, uint> rez in rezlist)
@@ -605,7 +672,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
605 672
606 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) 673 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
607 { 674 {
608 DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); 675 Vector3 pos = new Vector3(2.5f, 0f, 0f);
676 pos *= ((ScenePresence)sp).Rotation;
677 pos += sp.AbsolutePosition;
678 DetachSingleAttachmentToGround(sp, soLocalId, pos, Quaternion.Identity);
609 } 679 }
610 680
611 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) 681 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
@@ -649,26 +719,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
649 if (changed && m_scene.AvatarFactory != null) 719 if (changed && m_scene.AvatarFactory != null)
650 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 720 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
651 721
722 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
723
652 sp.RemoveAttachment(so); 724 sp.RemoveAttachment(so);
653 so.FromItemID = UUID.Zero; 725 so.FromItemID = UUID.Zero;
654 726
727 so.AttachedAvatar = UUID.Zero;
728 so.ClearPartAttachmentData();
729
655 SceneObjectPart rootPart = so.RootPart; 730 SceneObjectPart rootPart = so.RootPart;
731
732 rootPart.SetParentLocalId(0);
656 so.AbsolutePosition = absolutePos; 733 so.AbsolutePosition = absolutePos;
657 if (absoluteRot != Quaternion.Identity) 734 if (absoluteRot != Quaternion.Identity)
658 { 735 {
659 so.UpdateGroupRotationR(absoluteRot); 736 so.UpdateGroupRotationR(absoluteRot);
660 } 737 }
661 so.AttachedAvatar = UUID.Zero; 738
662 rootPart.SetParentLocalId(0);
663 so.ClearPartAttachmentData();
664 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive);
665 so.HasGroupChanged = true;
666 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
667 rootPart.Rezzed = DateTime.Now;
668 rootPart.RemFlag(PrimFlags.TemporaryOnRez); 739 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
740
741 so.ApplyPhysics();
742
743 rootPart.Rezzed = DateTime.Now;
669 so.AttachToBackup(); 744 so.AttachToBackup();
670 m_scene.EventManager.TriggerParcelPrimCountTainted(); 745 m_scene.EventManager.TriggerParcelPrimCountTainted();
671 rootPart.ScheduleFullUpdate(); 746
672 rootPart.ClearUndoState(); 747 rootPart.ClearUndoState();
673 748
674 List<UUID> uuids = new List<UUID>(); 749 List<UUID> uuids = new List<UUID>();
@@ -678,6 +753,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
678 } 753 }
679 754
680 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 755 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
756
757 // Attach (NULL) stops scripts. We don't want that. Resume them.
758 so.ResumeScripts();
759 so.HasGroupChanged = true;
760 so.RootPart.ScheduleFullUpdate();
761 so.ScheduleGroupForTerseUpdate();
681 } 762 }
682 763
683 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 764 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
@@ -691,9 +772,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
691 return; 772 return;
692 } 773 }
693 774
775 // If this didn't come from inventory, it also shouldn't go there
776 // on detach. It's likely a temp attachment.
777 if (so.FromItemID == UUID.Zero)
778 {
779 // Retirn value is ignored
780 PrepareScriptInstanceForSave(so, true);
781
782 lock (sp.AttachmentsSyncLock)
783 {
784 bool changed = sp.Appearance.DetachAttachment(so.FromItemID);
785 if (changed && m_scene.AvatarFactory != null)
786 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
787
788 sp.RemoveAttachment(so);
789 }
790
791 m_scene.DeleteSceneObject(so, false, false);
792 so.RemoveScriptInstances(true);
793 so.Clear();
794
795 return;
796 }
797
694 if (DebugLevel > 0) 798 if (DebugLevel > 0)
695 m_log.DebugFormat( 799 m_log.DebugFormat(
696 "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}", 800 "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
697 so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name); 801 so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
698 802
699 // Scripts MUST be snapshotted before the object is 803 // Scripts MUST be snapshotted before the object is
@@ -716,14 +820,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
716 UpdateDetachedObject(sp, so, scriptedState); 820 UpdateDetachedObject(sp, so, scriptedState);
717 } 821 }
718 } 822 }
719 823
720 public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos) 824 public void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos)
721 { 825 {
722 if (!Enabled) 826 if (!Enabled)
723 return; 827 return;
724 828
725 sog.UpdateGroupPosition(pos); 829 sog.UpdateGroupPosition(pos);
726 sog.HasGroupChanged = true; 830 sog.HasGroupChanged = true;
727 } 831 }
728 832
729 #endregion 833 #endregion
@@ -732,7 +836,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
732 836
733 // This is public but is not part of the IAttachmentsModule interface. 837 // This is public but is not part of the IAttachmentsModule interface.
734 // RegionCombiner module needs to poke at it to deliver client events. 838 // RegionCombiner module needs to poke at it to deliver client events.
735 // This breaks the encapsulation of the module and should get fixed somehow. 839 // This breaks the encapsulation of the module and should get fixed somehow.
736 public void SubscribeToClientEvents(IClientAPI client) 840 public void SubscribeToClientEvents(IClientAPI client)
737 { 841 {
738 client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv; 842 client.OnRezSingleAttachmentFromInv += Client_OnRezSingleAttachmentFromInv;
@@ -745,7 +849,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
745 849
746 // This is public but is not part of the IAttachmentsModule interface. 850 // This is public but is not part of the IAttachmentsModule interface.
747 // RegionCombiner module needs to poke at it to deliver client events. 851 // RegionCombiner module needs to poke at it to deliver client events.
748 // This breaks the encapsulation of the module and should get fixed somehow. 852 // This breaks the encapsulation of the module and should get fixed somehow.
749 public void UnsubscribeFromClientEvents(IClientAPI client) 853 public void UnsubscribeFromClientEvents(IClientAPI client)
750 { 854 {
751 client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv; 855 client.OnRezSingleAttachmentFromInv -= Client_OnRezSingleAttachmentFromInv;
@@ -791,11 +895,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
791 895
792 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); 896 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState);
793 897
794 InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); 898 InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, grp.FromItemID);
795 item = m_scene.InventoryService.GetItem(item);
796 899
797 if (item != null) 900 if (item != null)
798 { 901 {
902 // attach is rez, need to update permissions
903 item.Flags &= ~(uint)(InventoryItemFlags.ObjectSlamPerm | InventoryItemFlags.ObjectOverwriteBase |
904 InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup |
905 InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner);
906
907 uint permsBase = (uint)(PermissionMask.Copy | PermissionMask.Transfer |
908 PermissionMask.Modify | PermissionMask.Move |
909 PermissionMask.Export | PermissionMask.FoldedMask);
910
911 permsBase &= grp.CurrentAndFoldedNextPermissions();
912 permsBase |= (uint)PermissionMask.Move;
913 item.BasePermissions = permsBase;
914 item.CurrentPermissions = permsBase;
915 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask | (uint)PermissionMask.Move;
916 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
917 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
918 item.CurrentPermissions &=
919 ((uint)PermissionMask.Copy |
920 (uint)PermissionMask.Transfer |
921 (uint)PermissionMask.Modify |
922 (uint)PermissionMask.Move |
923 (uint)PermissionMask.Export |
924 (uint)PermissionMask.FoldedMask); // Preserve folded permissions ??
925
799 AssetBase asset = m_scene.CreateAsset( 926 AssetBase asset = m_scene.CreateAsset(
800 grp.GetPartName(grp.LocalId), 927 grp.GetPartName(grp.LocalId),
801 grp.GetPartDescription(grp.LocalId), 928 grp.GetPartDescription(grp.LocalId),
@@ -826,7 +953,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
826 /// Attach this scene object to the given avatar. 953 /// Attach this scene object to the given avatar.
827 /// </summary> 954 /// </summary>
828 /// <remarks> 955 /// <remarks>
829 /// This isn't publicly available since attachments should always perform the corresponding inventory 956 /// This isn't publicly available since attachments should always perform the corresponding inventory
830 /// operation (to show the attach in user inventory and update the asset with positional information). 957 /// operation (to show the attach in user inventory and update the asset with positional information).
831 /// </remarks> 958 /// </remarks>
832 /// <param name="sp"></param> 959 /// <param name="sp"></param>
@@ -846,16 +973,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
846 m_scene.DeleteFromStorage(so.UUID); 973 m_scene.DeleteFromStorage(so.UUID);
847 m_scene.EventManager.TriggerParcelPrimCountTainted(); 974 m_scene.EventManager.TriggerParcelPrimCountTainted();
848 975
849 so.AttachedAvatar = sp.UUID;
850 976
851 if (so.RootPart.PhysActor != null) 977 foreach (SceneObjectPart part in so.Parts)
852 so.RootPart.RemoveFromPhysics(); 978 {
979// if (part.KeyframeMotion != null)
980// part.KeyframeMotion.Suspend();
981
982 if (part.PhysActor != null)
983 {
984 part.RemoveFromPhysics();
985 }
986 }
853 987
854 so.AbsolutePosition = attachOffset;
855 so.RootPart.AttachedPos = attachOffset;
856 so.IsAttachment = true;
857 so.RootPart.SetParentLocalId(sp.LocalId); 988 so.RootPart.SetParentLocalId(sp.LocalId);
989 so.AttachedAvatar = sp.UUID;
858 so.AttachmentPoint = attachmentpoint; 990 so.AttachmentPoint = attachmentpoint;
991 so.RootPart.AttachedPos = attachOffset;
992 so.AbsolutePosition = attachOffset;
993 so.IsAttachment = true;
859 994
860 sp.AddAttachment(so); 995 sp.AddAttachment(so);
861 996
@@ -879,7 +1014,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
879 1014
880 // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update 1015 // Fudge below is an extremely unhelpful comment. It's probably here so that the scheduled full update
881 // will succeed, as that will not update if an attachment is selected. 1016 // will succeed, as that will not update if an attachment is selected.
882 so.IsSelected = false; // fudge.... 1017 so.IsSelected = false; // fudge....
883 1018
884 so.ScheduleGroupForFullUpdate(); 1019 so.ScheduleGroupForFullUpdate();
885 } 1020 }
@@ -923,7 +1058,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
923 /// </summary> 1058 /// </summary>
924 /// <remarks> 1059 /// <remarks>
925 /// This involves triggering the detach event and getting the script state (which also stops the script) 1060 /// This involves triggering the detach event and getting the script state (which also stops the script)
926 /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a 1061 /// This MUST be done outside sp.AttachmentsSyncLock, since otherwise there is a chance of deadlock if a
927 /// running script is performing attachment operations. 1062 /// running script is performing attachment operations.
928 /// </remarks> 1063 /// </remarks>
929 /// <returns> 1064 /// <returns>
@@ -939,7 +1074,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
939 if (fireDetachEvent) 1074 if (fireDetachEvent)
940 { 1075 {
941 m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero); 1076 m_scene.EventManager.TriggerOnAttach(grp.LocalId, grp.FromItemID, UUID.Zero);
942
943 // Allow detach event time to do some work before stopping the script 1077 // Allow detach event time to do some work before stopping the script
944 Thread.Sleep(2); 1078 Thread.Sleep(2);
945 } 1079 }
@@ -971,6 +1105,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
971 // Remove the object from the scene so no more updates 1105 // Remove the object from the scene so no more updates
972 // are sent. Doing this before the below changes will ensure 1106 // are sent. Doing this before the below changes will ensure
973 // updates can't cause "HUD artefacts" 1107 // updates can't cause "HUD artefacts"
1108
974 m_scene.DeleteSceneObject(so, false, false); 1109 m_scene.DeleteSceneObject(so, false, false);
975 1110
976 // Prepare sog for storage 1111 // Prepare sog for storage
@@ -989,23 +1124,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
989 1124
990 // Now, remove the scripts 1125 // Now, remove the scripts
991 so.RemoveScriptInstances(true); 1126 so.RemoveScriptInstances(true);
1127 so.Clear();
992 } 1128 }
993 1129
994 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 1130 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
995 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) 1131 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
996 { 1132 {
997 if (m_invAccessModule == null) 1133 if (m_invAccessModule == null)
998 return null; 1134 return null;
999 1135
1000 SceneObjectGroup objatt; 1136 SceneObjectGroup objatt;
1001 1137
1138 UUID rezGroupID;
1139
1140 // This will fail if the user aborts login. sp will exist
1141 // but ControllintClient will be null.
1142 try
1143 {
1144 rezGroupID = sp.ControllingClient.ActiveGroupId;
1145 }
1146 catch
1147 {
1148 return null;
1149 }
1150
1002 if (itemID != UUID.Zero) 1151 if (itemID != UUID.Zero)
1003 objatt = m_invAccessModule.RezObject(sp.ControllingClient, 1152 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
1004 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 1153 itemID, rezGroupID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
1005 false, false, sp.UUID, true); 1154 false, false, sp.UUID, true);
1006 else 1155 else
1007 objatt = m_invAccessModule.RezObject(sp.ControllingClient, 1156 objatt = m_invAccessModule.RezObject(sp.ControllingClient,
1008 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 1157 null, rezGroupID, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
1009 false, false, sp.UUID, true); 1158 false, false, sp.UUID, true);
1010 1159
1011 if (objatt == null) 1160 if (objatt == null)
@@ -1018,7 +1167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1018 } 1167 }
1019 else if (itemID == UUID.Zero) 1168 else if (itemID == UUID.Zero)
1020 { 1169 {
1021 // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is 1170 // We need to have a FromItemID for multiple attachments on a single attach point to appear. This is
1022 // true on Singularity 1.8.5 and quite possibly other viewers as well. As NPCs don't have an inventory 1171 // true on Singularity 1.8.5 and quite possibly other viewers as well. As NPCs don't have an inventory
1023 // we will satisfy this requirement by inserting a random UUID. 1172 // we will satisfy this requirement by inserting a random UUID.
1024 objatt.FromItemID = UUID.Random(); 1173 objatt.FromItemID = UUID.Random();
@@ -1043,6 +1192,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1043 // This will throw if the attachment fails 1192 // This will throw if the attachment fails
1044 try 1193 try
1045 { 1194 {
1195 if (doc != null)
1196 {
1197 objatt.LoadScriptState(doc);
1198 objatt.ResetOwnerChangeFlag();
1199 }
1200
1046 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); 1201 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append);
1047 } 1202 }
1048 catch (Exception e) 1203 catch (Exception e)
@@ -1058,7 +1213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1058 } 1213 }
1059 1214
1060 if (tainted) 1215 if (tainted)
1061 objatt.HasGroupChanged = true; 1216 objatt.HasGroupChanged = true;
1062 1217
1063 if (ThrottlePer100PrimsRezzed > 0) 1218 if (ThrottlePer100PrimsRezzed > 0)
1064 { 1219 {
@@ -1100,8 +1255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1100 return; 1255 return;
1101 } 1256 }
1102 1257
1103 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); 1258 InventoryItemBase item = m_scene.InventoryService.GetItem(sp.UUID, itemID);
1104 item = m_scene.InventoryService.GetItem(item);
1105 if (item == null) 1259 if (item == null)
1106 return; 1260 return;
1107 1261
@@ -1185,7 +1339,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1185 if (part == null) 1339 if (part == null)
1186 return; 1340 return;
1187 1341
1188 if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) 1342 SceneObjectGroup group = part.ParentGroup;
1343
1344 if (!m_scene.Permissions.CanTakeObject(group, sp))
1189 { 1345 {
1190 remoteClient.SendAgentAlertMessage( 1346 remoteClient.SendAgentAlertMessage(
1191 "You don't have sufficient permissions to attach this object", false); 1347 "You don't have sufficient permissions to attach this object", false);
@@ -1197,7 +1353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1197 AttachmentPt &= 0x7f; 1353 AttachmentPt &= 0x7f;
1198 1354
1199 // Calls attach with a Zero position 1355 // Calls attach with a Zero position
1200 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) 1356 if (AttachObject(sp, group , AttachmentPt, false, true, append))
1201 { 1357 {
1202 if (DebugLevel > 0) 1358 if (DebugLevel > 0)
1203 m_log.Debug( 1359 m_log.Debug(
@@ -1205,7 +1361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1205 + ", AttachmentPoint: " + AttachmentPt); 1361 + ", AttachmentPoint: " + AttachmentPt);
1206 1362
1207 // Save avatar attachment information 1363 // Save avatar attachment information
1208 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1364 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
1209 } 1365 }
1210 } 1366 }
1211 catch (Exception e) 1367 catch (Exception e)
@@ -1222,7 +1378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1222 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 1378 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
1223 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); 1379 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
1224 1380
1225 if (sp != null && group != null && group.FromItemID != UUID.Zero) 1381 if (sp != null && group != null)
1226 DetachSingleAttachmentToInv(sp, group); 1382 DetachSingleAttachmentToInv(sp, group);
1227 } 1383 }
1228 1384
@@ -1256,7 +1412,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1256 if (sp != null) 1412 if (sp != null)
1257 DetachSingleAttachmentToGround(sp, soLocalId); 1413 DetachSingleAttachmentToGround(sp, soLocalId);
1258 } 1414 }
1259
1260 #endregion 1415 #endregion
1261 } 1416 }
1262} 1417}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 0ac3add..941853c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -55,6 +55,7 @@ using OpenSim.Tests.Common;
55 55
56namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests 56namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
57{ 57{
58/*
58 /// <summary> 59 /// <summary>
59 /// Attachment tests 60 /// Attachment tests
60 /// </summary> 61 /// </summary>
@@ -200,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
200 Assert.That(so.Backup, Is.True); 201 Assert.That(so.Backup, Is.True);
201 202
202 m_numberOfAttachEventsFired = 0; 203 m_numberOfAttachEventsFired = 0;
203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 204 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false);
204 205
205 // Check status on scene presence 206 // Check status on scene presence
206 Assert.That(sp.HasAttachments(), Is.True); 207 Assert.That(sp.HasAttachments(), Is.True);
@@ -215,11 +216,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
215 Assert.That(attSo.Backup, Is.False); 216 Assert.That(attSo.Backup, Is.False);
216 217
217 // Check item status 218 // Check item status
218 Assert.That( 219// Assert.That(
219 sp.Appearance.GetAttachpoint(attSo.FromItemID), 220// sp.Appearance.GetAttachpoint(attSo.FromItemID),
220 Is.EqualTo((int)AttachmentPoint.Chest)); 221// Is.EqualTo((int)AttachmentPoint.Chest));
221 222
222 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 223 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
223 Assert.That(attachmentItem, Is.Not.Null); 224 Assert.That(attachmentItem, Is.Not.Null);
224 Assert.That(attachmentItem.Name, Is.EqualTo(attName)); 225 Assert.That(attachmentItem.Name, Is.EqualTo(attName));
225 226
@@ -262,11 +263,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
262 Assert.That(attSo.IsTemporary, Is.False); 263 Assert.That(attSo.IsTemporary, Is.False);
263 264
264 // Check item status 265 // Check item status
265 Assert.That( 266// Assert.That(
266 sp.Appearance.GetAttachpoint(attSo.FromItemID), 267// sp.Appearance.GetAttachpoint(attSo.FromItemID),
267 Is.EqualTo((int)AttachmentPoint.LeftHand)); 268// Is.EqualTo((int)AttachmentPoint.LeftHand));
268 269
269 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 270 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
270 Assert.That(attachmentItem, Is.Not.Null); 271 Assert.That(attachmentItem, Is.Not.Null);
271 Assert.That(attachmentItem.Name, Is.EqualTo(so.Name)); 272 Assert.That(attachmentItem.Name, Is.EqualTo(so.Name));
272 273
@@ -281,7 +282,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
281 282
282 // Test wearing a different attachment from the ground. 283 // Test wearing a different attachment from the ground.
283 { 284 {
284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 285 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false);
285 286
286 // Check status on scene presence 287 // Check status on scene presence
287 Assert.That(sp.HasAttachments(), Is.True); 288 Assert.That(sp.HasAttachments(), Is.True);
@@ -295,11 +296,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
295 Assert.That(attSo.IsTemporary, Is.False); 296 Assert.That(attSo.IsTemporary, Is.False);
296 297
297 // Check item status 298 // Check item status
298 Assert.That( 299// Assert.That(
299 sp.Appearance.GetAttachpoint(attSo.FromItemID), 300// sp.Appearance.GetAttachpoint(attSo.FromItemID),
300 Is.EqualTo((int)AttachmentPoint.LeftHand)); 301// Is.EqualTo((int)AttachmentPoint.LeftHand));
301 302
302 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 303 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
303 Assert.That(attachmentItem, Is.Not.Null); 304 Assert.That(attachmentItem, Is.Not.Null);
304 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); 305 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
305 306
@@ -314,7 +315,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
314 315
315 // Test rewearing an already worn attachment from ground. Nothing should happen. 316 // Test rewearing an already worn attachment from ground. Nothing should happen.
316 { 317 {
317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 318 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false);
318 319
319 // Check status on scene presence 320 // Check status on scene presence
320 Assert.That(sp.HasAttachments(), Is.True); 321 Assert.That(sp.HasAttachments(), Is.True);
@@ -328,11 +329,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
328 Assert.That(attSo.IsTemporary, Is.False); 329 Assert.That(attSo.IsTemporary, Is.False);
329 330
330 // Check item status 331 // Check item status
331 Assert.That( 332// Assert.That(
332 sp.Appearance.GetAttachpoint(attSo.FromItemID), 333// sp.Appearance.GetAttachpoint(attSo.FromItemID),
333 Is.EqualTo((int)AttachmentPoint.LeftHand)); 334// Is.EqualTo((int)AttachmentPoint.LeftHand));
334 335
335 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); 336 InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID);
336 Assert.That(attachmentItem, Is.Not.Null); 337 Assert.That(attachmentItem, Is.Not.Null);
337 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); 338 Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name));
338 339
@@ -372,7 +373,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
372 sp2.AbsolutePosition = new Vector3(0, 0, 0); 373 sp2.AbsolutePosition = new Vector3(0, 0, 0);
373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 374 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
374 375
375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 376 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false);
376 377
377 Assert.That(sp.HasAttachments(), Is.False); 378 Assert.That(sp.HasAttachments(), Is.False);
378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 379 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -410,8 +411,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
410 Assert.IsFalse(attSo.Backup); 411 Assert.IsFalse(attSo.Backup);
411 412
412 // Check appearance status 413 // Check appearance status
413 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 414// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
414 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 415// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
415 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 416 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
416 417
417 // Check events 418 // Check events
@@ -435,8 +436,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
435 Assert.That(attSo.IsTemporary, Is.False); 436 Assert.That(attSo.IsTemporary, Is.False);
436 437
437 // Check appearance status 438 // Check appearance status
438 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 439// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
439 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 440// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
440 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 441 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
441 442
442 // Check events 443 // Check events
@@ -474,8 +475,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
474 Assert.That(attSo.IsAttachment); 475 Assert.That(attSo.IsAttachment);
475 476
476 // Check appearance status 477 // Check appearance status
477 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 478// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
478 Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); 479// Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
479 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 480 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
480 481
481 // Check events 482 // Check events
@@ -484,7 +485,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
484 485
485 // Test wearing a second attachment at the same position 486 // Test wearing a second attachment at the same position
486 // Until multiple attachments at one point is implemented, this will remove the first attachment 487 // Until multiple attachments at one point is implemented, this will remove the first attachment
487 // This test relies on both attachments having the same default attachment point (in this case LeftHand 488 // This test relies on both attachments having the same default attachment point (in this case LeftHand
488 // since none other has been set). 489 // since none other has been set).
489 { 490 {
490 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); 491 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default);
@@ -499,8 +500,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
499 Assert.That(attSo.IsAttachment); 500 Assert.That(attSo.IsAttachment);
500 501
501 // Check appearance status 502 // Check appearance status
502 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 503// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
503 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); 504// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
504 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 505 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
505 506
506 // Check events 507 // Check events
@@ -521,8 +522,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
521 Assert.That(attSo.IsAttachment); 522 Assert.That(attSo.IsAttachment);
522 523
523 // Check appearance status 524 // Check appearance status
524 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); 525// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1));
525 Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); 526// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand));
526 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 527 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
527 528
528 // Check events 529 // Check events
@@ -556,6 +557,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
556 // In the future, we need to be able to do this programatically more predicably. 557 // In the future, we need to be able to do this programatically more predicably.
557 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 558 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
558 559
560 m_chatEvent.Reset();
559 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 561 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
560 562
561 m_chatEvent.WaitOne(60000); 563 m_chatEvent.WaitOne(60000);
@@ -596,10 +598,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
596 Assert.That(attachments.Count, Is.EqualTo(0)); 598 Assert.That(attachments.Count, Is.EqualTo(0));
597 599
598 // Check appearance status 600 // Check appearance status
599 Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0)); 601// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0));
600 602
601 // Check item status 603 // Check item status
602 Assert.That(scene.InventoryService.GetItem(new InventoryItemBase(attItem.ID)), Is.Null); 604 Assert.That(scene.InventoryService.GetItem(sp.UUID, attItem.ID), Is.Null);
603 605
604 // Check object in scene 606 // Check object in scene
605 SceneObjectGroup soInScene = scene.GetSceneObjectGroup("att"); 607 SceneObjectGroup soInScene = scene.GetSceneObjectGroup("att");
@@ -634,7 +636,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
634 Assert.That(attachments.Count, Is.EqualTo(0)); 636 Assert.That(attachments.Count, Is.EqualTo(0));
635 637
636 // Check item status 638 // Check item status
637 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); 639// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
638 640
639 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); 641 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
640 642
@@ -669,15 +671,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
669 // In the future, we need to be able to do this programatically more predicably. 671 // In the future, we need to be able to do this programatically more predicably.
670 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 672 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
671 673
674 m_chatEvent.Reset();
672 SceneObjectGroup rezzedSo 675 SceneObjectGroup rezzedSo
673 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 676 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
674 677
675 // Wait for chat to signal rezzed script has been started. 678 // Wait for chat to signal rezzed script has been started.
676 m_chatEvent.WaitOne(60000); 679 m_chatEvent.WaitOne(60000);
677 680
678 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); 681 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo);
679 682
680 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); 683 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem.Owner, userItem.ID);
681 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); 684 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
682 685
683 // TODO: It would probably be better here to check script state via the saving and retrieval of state 686 // TODO: It would probably be better here to check script state via the saving and retrieval of state
@@ -689,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 692 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
690 693
691 // Re-rez the attachment to check script running state 694 // Re-rez the attachment to check script running state
692 SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 695 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
693 696
694 // Wait for chat to signal rezzed script has been started. 697 // Wait for chat to signal rezzed script has been started.
695 m_chatEvent.WaitOne(60000); 698 m_chatEvent.WaitOne(60000);
@@ -719,13 +722,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
719 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 722 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
720 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 723 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
721 724
722 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 725 UUID rezzedAttID = presence.GetAttachments()[0].UUID;
723 726
724 m_numberOfAttachEventsFired = 0; 727 m_numberOfAttachEventsFired = 0;
725 scene.CloseAgent(presence.UUID, false); 728 scene.CloseAgent(presence.UUID, false);
726 729
727 // Check that we can't retrieve this attachment from the scene. 730 // Check that we can't retrieve this attachment from the scene.
728 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 731 Assert.That(scene.GetSceneObjectGroup(rezzedAttID), Is.Null);
729 732
730 // Check events 733 // Check events
731 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 734 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
@@ -802,7 +805,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
802 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 805 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
803 } 806 }
804 807
805/* 808
806 [Test] 809 [Test]
807 public void TestSameSimulatorNeighbouringRegionsTeleportV1() 810 public void TestSameSimulatorNeighbouringRegionsTeleportV1()
808 { 811 {
@@ -842,7 +845,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
842 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); 845 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
843 846
844 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour 847 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
845 lscm.ServiceVersion = 0.1f; 848 //lscm.ServiceVersion = 0.1f;
846 849
847 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); 850 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
848 851
@@ -910,7 +913,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
910 // Check events 913 // Check events
911 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 914 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
912 } 915 }
913*/ 916
914 917
915 [Test] 918 [Test]
916 public void TestSameSimulatorNeighbouringRegionsTeleportV2() 919 public void TestSameSimulatorNeighbouringRegionsTeleportV2()
@@ -972,8 +975,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
972 // Both these operations will occur on different threads and will wait for each other. 975 // Both these operations will occur on different threads and will wait for each other.
973 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1 976 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
974 // test protocol, where we are trying to avoid unpredictable async operations in regression tests. 977 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
975 tc.OnTestClientSendRegionTeleport 978 tc.OnTestClientSendRegionTeleport
976 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) 979 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
977 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null); 980 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
978 981
979 m_numberOfAttachEventsFired = 0; 982 m_numberOfAttachEventsFired = 0;
@@ -1023,4 +1026,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
1023 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 1026 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
1024 } 1027 }
1025 } 1028 }
1029*/
1026} 1030}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index cfb082b..4abac43 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures); 77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures);
78 78
79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
80 } 80 }
81 81
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
166 } 166 }
167 167
168 /// <summary> 168 /// <summary>
169 /// Set appearance data (texture asset IDs and slider settings) 169 /// Set appearance data (texture asset IDs and slider settings)
170 /// </summary> 170 /// </summary>
171 /// <param name="sp"></param> 171 /// <param name="sp"></param>
172 /// <param name="texture"></param> 172 /// <param name="texture"></param>
@@ -188,29 +188,9 @@ 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
215 if (textureEntry != null) 195 if (textureEntry != null)
216 { 196 {
@@ -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();
@@ -289,7 +267,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
289 WearableCacheItem[] items = sp.Appearance.WearableCacheItems; 267 WearableCacheItem[] items = sp.Appearance.WearableCacheItems;
290 //foreach (WearableCacheItem item in items) 268 //foreach (WearableCacheItem item in items)
291 //{ 269 //{
292 270
293 //} 271 //}
294 return items; 272 return items;
295 } 273 }
@@ -310,23 +288,25 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
310 if (bakedTextures.Count == 0) 288 if (bakedTextures.Count == 0)
311 return false; 289 return false;
312 290
291 IAssetCache cache = sp.Scene.RequestModuleInterface<IAssetCache>();
292 if(cache == null)
293 return true; // no baked local caching so nothing to do
294
313 foreach (BakeType bakeType in bakedTextures.Keys) 295 foreach (BakeType bakeType in bakedTextures.Keys)
314 { 296 {
315 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType]; 297 Primitive.TextureEntryFace bakedTextureFace = bakedTextures[bakeType];
316 298
317 if (bakedTextureFace == null) 299 if (bakedTextureFace == null)
318 {
319 // This can happen legitimately, since some baked textures might not exist
320 //m_log.WarnFormat(
321 // "[AV FACTORY]: No texture ID set for {0} for {1} in {2} not found when trying to save permanently",
322 // bakeType, sp.Name, m_scene.RegionInfo.RegionName);
323 continue; 300 continue;
324 }
325 301
326 AssetBase asset = m_scene.AssetService.Get(bakedTextureFace.TextureID.ToString()); 302 AssetBase asset;
303 cache.Get(bakedTextureFace.TextureID.ToString(), out asset);
327 304
328 if (asset != null) 305 if (asset != null && asset.Local)
329 { 306 {
307 // cache does not update asset contents
308 cache.Expire(bakedTextureFace.TextureID.ToString());
309
330 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars 310 // Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars
331 asset.ID = asset.FullID.ToString(); 311 asset.ID = asset.FullID.ToString();
332 312
@@ -334,7 +314,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
334 asset.Local = false; 314 asset.Local = false;
335 m_scene.AssetService.Store(asset); 315 m_scene.AssetService.Store(asset);
336 } 316 }
337 else 317
318 if (asset == null)
338 { 319 {
339 m_log.WarnFormat( 320 m_log.WarnFormat(
340 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently", 321 "[AV FACTORY]: Baked texture id {0} not found for bake {1} for avatar {2} in {3} when trying to save permanently",
@@ -377,116 +358,366 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
377 } 358 }
378 } 359 }
379 360
380 public bool ValidateBakedTextureCache(IScenePresence sp) 361 // called on textures update
362 public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
381 { 363 {
382 bool defonly = true; // are we only using default textures 364 if(cacheItems == null)
383 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 365 return false;
384 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 366
385 WearableCacheItem[] wearableCache = null; 367 // npcs dont have baked cache
386 368 if (((ScenePresence)sp).IsNPC)
387 // Cache wearable data for teleport. 369 return true;
388 // Only makes sense if there's a bake module and a cache module 370
389 if (bakedModule != null && cache != null) 371 // uploaded baked textures will be in assets local cache
372 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
373 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
374
375 int validDirtyBakes = 0;
376 int hits = 0;
377
378 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
379 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
380
381 if (wearableCache == null)
382 {
383 wearableCache = WearableCacheItem.GetDefaultCacheItem();
384 }
385
386 List<UUID> missing = new List<UUID>();
387
388 bool haveSkirt = (wearableCache[19].TextureID != UUID.Zero);
389 bool haveNewSkirt = false;
390
391 // Process received baked textures
392 for (int i = 0; i < cacheItems.Length; i++)
390 { 393 {
391 try 394 int idx = (int)cacheItems[i].TextureIndex;
395 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
396
397 // No face
398 if (face == null)
392 { 399 {
393 wearableCache = bakedModule.Get(sp.UUID); 400 // for some reason viewer is cleaning this
401 if(idx != 19) // skirt is optional
402 {
403 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
404 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
405 }
406 wearableCache[idx].CacheId = UUID.Zero;
407 wearableCache[idx].TextureID = UUID.Zero;
408 wearableCache[idx].TextureAsset = null;
409 continue;
394 } 410 }
395 catch (Exception) 411 else
396 { 412 {
413 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
414 {
415 wearableCache[idx].CacheId = UUID.Zero;
416 wearableCache[idx].TextureID = UUID.Zero;
417 wearableCache[idx].TextureAsset = null;
418 continue;
419 }
397 420
398 } 421 if(idx == 19)
399 if (wearableCache != null) 422 haveNewSkirt = true;
400 { 423/*
401 for (int i = 0; i < wearableCache.Length; i++) 424 if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
402 { 425 {
403 cache.Cache(wearableCache[i].TextureAsset); 426 if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
427 {
428 wearableCache[idx].CacheId = cacheItems[i].CacheId;
429 validDirtyBakes++;
430
431 //assuming this can only happen if asset is in cache
432 }
433 hits++;
434 continue;
435 }
436*/
437 wearableCache[idx].TextureAsset = null;
438 if (cache != null)
439 {
440 AssetBase asb = null;
441 cache.Get(face.TextureID.ToString(), out asb);
442 wearableCache[idx].TextureAsset = asb;
443 }
444
445 if (wearableCache[idx].TextureAsset != null)
446 {
447 if ( wearableCache[idx].TextureID != face.TextureID ||
448 wearableCache[idx].CacheId != cacheItems[i].CacheId)
449 validDirtyBakes++;
450
451 wearableCache[idx].TextureID = face.TextureID;
452 wearableCache[idx].CacheId = cacheItems[i].CacheId;
453 hits++;
454 }
455 else
456 {
457 wearableCache[idx].CacheId = UUID.Zero;
458 wearableCache[idx].TextureID = UUID.Zero;
459 wearableCache[idx].TextureAsset = null;
460 missing.Add(face.TextureID);
461 continue;
404 } 462 }
405 } 463 }
406 } 464 }
407 /* 465
408 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 466 // handle optional skirt case
409 if (invService.GetRootFolder(userID) != null) 467 if(!haveNewSkirt && haveSkirt)
468 {
469 wearableCache[19].CacheId = UUID.Zero;
470 wearableCache[19].TextureID = UUID.Zero;
471 wearableCache[19].TextureAsset = null;
472 validDirtyBakes++;
473 }
474
475 sp.Appearance.WearableCacheItems = wearableCache;
476
477 if (missing.Count > 0)
410 { 478 {
411 WearableCacheItem[] wearableCache = null; 479 foreach (UUID id in missing)
412 if (bakedModule != null) 480 sp.ControllingClient.SendRebakeAvatarTextures(id);
481 }
482
483 if (validDirtyBakes > 0 && hits == cacheItems.Length)
484 {
485 // if we got a full set of baked textures save all in BakedTextureModule
486 if (m_BakedTextureModule != null)
413 { 487 {
414 try 488 m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}",
489 hits.ToString(), validDirtyBakes.ToString(), missing.Count);
490
491 m_BakedTextureModule.Store(sp.UUID, wearableCache);
492 }
493 }
494 else
495 m_log.DebugFormat("[UpdateBakedCache] cache hits: {0} changed entries: {1} rebakes {2}",
496 hits.ToString(), validDirtyBakes.ToString(), missing.Count);
497
498 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
499 {
500 int j = AvatarAppearance.BAKE_INDICES[iter];
501 sp.Appearance.WearableCacheItems[j].TextureAsset = null;
502// m_log.Debug("[UpdateBCache] {" + iter + "/" +
503// sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
504// sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
505// sp.Appearance.WearableCacheItems[j].TextureID);
506 }
507
508 return (hits == cacheItems.Length);
509 }
510
511 // called when we get a new root avatar
512 public bool ValidateBakedTextureCache(IScenePresence sp)
513 {
514 int hits = 0;
515
516 if (((ScenePresence)sp).IsNPC)
517 return true;
518
519 lock (m_setAppearanceLock)
520 {
521 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
522 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
523 WearableCacheItem[] bakedModuleCache = null;
524
525 if (cache == null)
526 return false;
527
528 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
529
530 // big debug
531 //m_log.DebugFormat("[AVFACTORY]: ValidateBakedTextureCache start for {0} {1}", sp.Name, sp.UUID);
532/*
533 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
534 {
535 int j = AvatarAppearance.BAKE_INDICES[iter];
536 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[j];
537 if (wearableCache == null)
538 {
539 if (face != null)
540 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- " + face.TextureID);
541 else
542 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- No texture");
543 }
544 else
545 {
546 if (face != null)
547 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " ft- " + face.TextureID +
548 "}: cc-" +
549 wearableCache[j].CacheId + ", ct-" +
550 wearableCache[j].TextureID
551 );
552 else
553 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t - No texture" +
554 "}: cc-" +
555 wearableCache[j].CacheId + ", ct-" +
556 wearableCache[j].TextureID
557 );
558 }
559 }
560*/
561
562 bool wearableCacheValid = false;
563 if (wearableCache == null)
564 {
565 wearableCache = WearableCacheItem.GetDefaultCacheItem();
566 }
567 else
568 {
569 // we may have received a full cache
570 // check same coerence and store
571 wearableCacheValid = true;
572 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
415 { 573 {
416 wearableCache = bakedModule.Get(userID); 574 int idx = AvatarAppearance.BAKE_INDICES[i];
417 appearance.WearableCacheItems = wearableCache; 575 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
418 appearance.WearableCacheItemsDirty = false; 576 if (face != null)
419 foreach (WearableCacheItem item in wearableCache)
420 { 577 {
421 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; 578 if (face.TextureID == wearableCache[idx].TextureID &&
579 face.TextureID != UUID.Zero)
580 {
581 if (wearableCache[idx].TextureAsset != null)
582 {
583 hits++;
584 wearableCache[idx].TextureAsset.Temporary = true;
585 wearableCache[idx].TextureAsset.Local = true;
586 cache.Cache(wearableCache[idx].TextureAsset);
587 wearableCache[idx].TextureAsset = null;
588 continue;
589 }
590
591 if (cache.Check((wearableCache[idx].TextureID).ToString()))
592 {
593 hits++;
594 continue;
595 }
596 }
597 wearableCacheValid = false;
422 } 598 }
423 } 599 }
424 catch (Exception) 600
601 wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
602 if (wearableCacheValid)
425 { 603 {
426 604 //m_log.Debug("[ValidateBakedCache] have valid local cache");
427 } 605 }
606 else
607 wearableCache[19].TextureAsset = null; // clear optional skirt
428 } 608 }
429 */
430 609
431 // Process the texture entry 610 bool checkExternal = false;
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 611
437 // No face, so lets check our baked service cache, teleport or login. 612 if (!wearableCacheValid)
438 if (face == null)
439 { 613 {
440 if (wearableCache != null) 614 hits = 0;
615 // only use external bake module on login condition check
616// ScenePresence ssp = null;
617// if (sp is ScenePresence)
441 { 618 {
442 // If we find the an appearance item, set it as the textureentry and the face 619// ssp = (ScenePresence)sp;
443 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); 620// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
444 if (searchitem != null) 621// bakedModule != null;
445 { 622
446 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); 623 // or do it anytime we dont have the cache
447 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; 624 checkExternal = bakedModule != null;
448 face = sp.Appearance.Texture.FaceTextures[idx]; 625 }
449 } 626 }
450 else 627
628 if (checkExternal)
629 {
630 bool gotbacked = false;
631
632 m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
633 try
634 {
635 bakedModuleCache = bakedModule.Get(sp.UUID);
636 }
637 catch (Exception e)
638 {
639 m_log.ErrorFormat(e.ToString());
640 bakedModuleCache = null;
641 }
642
643 if (bakedModuleCache != null)
644 {
645 //m_log.Debug("[ValidateBakedCache] got bakedModule " + bakedModuleCache.Length + " cached textures");
646
647 for (int i = 0; i < bakedModuleCache.Length; i++)
451 { 648 {
452 // if there is no texture entry and no baked cache, skip it 649 int j = (int)bakedModuleCache[i].TextureIndex;
453 continue; 650
651 if (bakedModuleCache[i].TextureAsset != null)
652 {
653 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
654 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
655 wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset;
656 bakedModuleCache[i].TextureAsset.Temporary = true;
657 bakedModuleCache[i].TextureAsset.Local = true;
658 cache.Cache(bakedModuleCache[i].TextureAsset);
659 }
454 } 660 }
661 gotbacked = true;
455 } 662 }
456 else 663
664 if (gotbacked)
457 { 665 {
458 //No texture entry face and no cache. Skip this face. 666 // force the ones we got
459 continue; 667 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
668 {
669 int idx = AvatarAppearance.BAKE_INDICES[i];
670 if(wearableCache[idx].TextureAsset == null)
671 {
672 if(idx == 19)
673 {
674 sp.Appearance.Texture.FaceTextures[idx] = null;
675 hits++;
676 }
677 continue;
678 }
679
680 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
681
682 if (face == null)
683 {
684 face = sp.Appearance.Texture.CreateFace((uint)idx);
685 sp.Appearance.Texture.FaceTextures[idx] = face;
686 }
687
688 face.TextureID = wearableCache[idx].TextureID;
689 hits++;
690 wearableCache[idx].TextureAsset = null;
691 }
460 } 692 }
461 } 693 }
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 694
467 // if the texture is one of the "defaults" then skip it 695 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 696
476 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
477 return false;
478 } 697 }
479 698
480// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 699 // debug
481 700 //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 701/*
483 return (defonly ? false : true); 702 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
703 {
704 int j = AvatarAppearance.BAKE_INDICES[iter];
705 m_log.Debug("[ValidateBakedCache] {" + iter + "/" +
706 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
707 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
708 sp.Appearance.WearableCacheItems[j].TextureID);
709 }
710*/
711 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
484 } 712 }
485 713
486 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 714 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
487 { 715 {
716 if (((ScenePresence)sp).IsNPC)
717 return 0;
718
488 int texturesRebaked = 0; 719 int texturesRebaked = 0;
489// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 720 IAssetCache cache = m_scene.RequestModuleInterface<IAssetCache>();
490 721
491 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) 722 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
492 { 723 {
@@ -497,31 +728,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
497 if (face == null) 728 if (face == null)
498 continue; 729 continue;
499 730
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) 731 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
509 continue; 732 continue;
510 733
511 if (missingTexturesOnly) 734 if (missingTexturesOnly)
512 { 735 {
513 if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) 736 if (cache != null && cache.Check(face.TextureID.ToString()))
514 { 737 {
515 continue; 738 continue;
516 } 739 }
517 else 740 else
518 { 741 {
519 // On inter-simulator teleports, this occurs if baked textures are not being stored by the
520 // grid asset service (which means that they are not available to the new region and so have
521 // to be re-requested from the client).
522 //
523 // The only available core OpenSimulator behaviour right now
524 // is not to store these textures, temporarily or otherwise.
525 m_log.DebugFormat( 742 m_log.DebugFormat(
526 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", 743 "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.",
527 face.TextureID, idx, sp.Name); 744 face.TextureID, idx, sp.Name);
@@ -605,7 +822,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
605 foreach (KeyValuePair<UUID, long> kvp in saves) 822 foreach (KeyValuePair<UUID, long> kvp in saves)
606 { 823 {
607 // We have to load the key and value into local parameters to avoid a race condition if we loop 824 // We have to load the key and value into local parameters to avoid a race condition if we loop
608 // around and load kvp with a different value before FireAndForget has launched its thread. 825 // around and load kvp with a different value before FireAndForget has launched its thread.
609 UUID avatarID = kvp.Key; 826 UUID avatarID = kvp.Key;
610 long sendTime = kvp.Value; 827 long sendTime = kvp.Value;
611 828
@@ -658,13 +875,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
658 875
659 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 876 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
660 877
661 // Trigger this here because it's the final step in the set/queue/save process for appearance setting. 878 // Trigger this here because it's the final step in the set/queue/save process for appearance setting.
662 // Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes). 879 // Everything has been updated and stored. Ensures bakes have been persisted (if option is set to persist bakes).
663 m_scene.EventManager.TriggerAvatarAppearanceChanged(sp); 880 m_scene.EventManager.TriggerAvatarAppearanceChanged(sp);
664 } 881 }
665 882
666 /// <summary> 883 /// <summary>
667 /// For a given set of appearance items, check whether the items are valid and add their asset IDs to 884 /// For a given set of appearance items, check whether the items are valid and add their asset IDs to
668 /// appearance data. 885 /// appearance data.
669 /// </summary> 886 /// </summary>
670 /// <param name='userID'></param> 887 /// <param name='userID'></param>
@@ -675,25 +892,27 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
675 892
676 if (invService.GetRootFolder(userID) != null) 893 if (invService.GetRootFolder(userID) != null)
677 { 894 {
678 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 895 for (int i = 0; i < appearance.Wearables.Length; i++)
679 { 896 {
680 for (int j = 0; j < appearance.Wearables[i].Count; j++) 897 for (int j = 0; j < appearance.Wearables[i].Count; j++)
681 { 898 {
682 if (appearance.Wearables[i][j].ItemID == UUID.Zero) 899 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
683 { 900 {
684 m_log.WarnFormat( 901 m_log.WarnFormat(
685 "[AVFACTORY]: Wearable item {0}:{1} for user {2} unexpectedly UUID.Zero. Ignoring.", 902 "[AVFACTORY]: Wearable item {0}:{1} for user {2} unexpectedly UUID.Zero. Ignoring.",
686 i, j, userID); 903 i, j, userID);
687 904
688 continue; 905 continue;
689 } 906 }
690 907
691 // Ignore ruth's assets 908 // Ignore ruth's assets
692 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 909 if (i < AvatarWearable.DefaultWearables.Length)
693 continue; 910 {
911 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
912 continue;
913 }
694 914
695 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 915 InventoryItemBase baseItem = invService.GetItem(userID, appearance.Wearables[i][j].ItemID);
696 baseItem = invService.GetItem(baseItem);
697 916
698 if (baseItem != null) 917 if (baseItem != null)
699 { 918 {
@@ -754,7 +973,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
754// case WearableType.Skin: 973// case WearableType.Skin:
755// //case WearableType.Underpants: 974// //case WearableType.Underpants:
756// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); 975// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
757// 976//
758// m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); 977// m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i);
759// resetwearable = true; 978// resetwearable = true;
760// break; 979// break;
@@ -762,7 +981,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
762// } 981// }
763// continue; 982// continue;
764// } 983// }
765// 984//
766// InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 985// InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
767// baseItem = invService.GetItem(baseItem); 986// baseItem = invService.GetItem(baseItem);
768// 987//
@@ -789,7 +1008,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
789// 1008//
790// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); 1009// TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
791// resetwearable = true; 1010// resetwearable = true;
792// 1011//
793// } 1012// }
794// } 1013// }
795// } 1014// }
@@ -798,7 +1017,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
798// if (appearance.Wearables[(int) WearableType.Eyes] == null) 1017// if (appearance.Wearables[(int) WearableType.Eyes] == null)
799// { 1018// {
800// m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); 1019// m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes));
801// 1020//
802// TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); 1021// TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
803// resetwearable = true; 1022// resetwearable = true;
804// } 1023// }
@@ -902,85 +1121,45 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
902 { 1121 {
903 UUID newInvItem = UUID.Random(); 1122 UUID newInvItem = UUID.Random();
904 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) 1123 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID)
905 { 1124 {
906 AssetID = 1125 AssetID = defaultwearable,
907 defaultwearable, 1126 AssetType = (int)FolderType.BodyPart,
908 AssetType 1127 CreatorId = userID.ToString(),
909 = 1128 //InvType = (int)InventoryType.Wearable,
910 (int) 1129 Description = "Failed Wearable Replacement",
911 FolderType 1130 Folder = invService.GetFolderForType(userID, FolderType.BodyPart).ID,
912 .BodyPart, 1131 Flags = (uint) type, Name = Enum.GetName(typeof (WearableType), type),
913 CreatorId 1132 BasePermissions = (uint) PermissionMask.Copy,
914 = 1133 CurrentPermissions = (uint) PermissionMask.Copy,
915 userID 1134 EveryOnePermissions = (uint) PermissionMask.Copy,
916 .ToString 1135 GroupPermissions = (uint) PermissionMask.Copy,
917 (), 1136 NextPermissions = (uint) PermissionMask.Copy
918 //InvType = (int)InventoryType.Wearable, 1137 };
919
920 Description
921 =
922 "Failed Wearable Replacement",
923 Folder =
924 invService
925 .GetFolderForType
926 (userID,
927 FolderType
928 .BodyPart)
929 .ID,
930 Flags = (uint) type,
931 Name = Enum.GetName(typeof (WearableType), type),
932 BasePermissions = (uint) PermissionMask.Copy,
933 CurrentPermissions = (uint) PermissionMask.Copy,
934 EveryOnePermissions = (uint) PermissionMask.Copy,
935 GroupPermissions = (uint) PermissionMask.Copy,
936 NextPermissions = (uint) PermissionMask.Copy
937 };
938 invService.AddItem(itembase); 1138 invService.AddItem(itembase);
939 UUID LinkInvItem = UUID.Random(); 1139 UUID LinkInvItem = UUID.Random();
940 itembase = new InventoryItemBase(LinkInvItem, userID) 1140 itembase = new InventoryItemBase(LinkInvItem, userID)
941 { 1141 {
942 AssetID = 1142 AssetID = newInvItem,
943 newInvItem, 1143 AssetType = (int)AssetType.Link,
944 AssetType 1144 CreatorId = userID.ToString(),
945 = 1145 InvType = (int) InventoryType.Wearable,
946 (int) 1146 Description = "Failed Wearable Replacement",
947 AssetType 1147 Folder = invService.GetFolderForType(userID, FolderType.CurrentOutfit).ID,
948 .Link, 1148 Flags = (uint) type,
949 CreatorId 1149 Name = Enum.GetName(typeof (WearableType), type),
950 = 1150 BasePermissions = (uint) PermissionMask.Copy,
951 userID 1151 CurrentPermissions = (uint) PermissionMask.Copy,
952 .ToString 1152 EveryOnePermissions = (uint) PermissionMask.Copy,
953 (), 1153 GroupPermissions = (uint) PermissionMask.Copy,
954 InvType = (int) InventoryType.Wearable, 1154 NextPermissions = (uint) PermissionMask.Copy
955 1155 };
956 Description
957 =
958 "Failed Wearable Replacement",
959 Folder =
960 invService
961 .GetFolderForType
962 (userID,
963 FolderType
964 .CurrentOutfit)
965 .ID,
966 Flags = (uint) type,
967 Name = Enum.GetName(typeof (WearableType), type),
968 BasePermissions = (uint) PermissionMask.Copy,
969 CurrentPermissions = (uint) PermissionMask.Copy,
970 EveryOnePermissions = (uint) PermissionMask.Copy,
971 GroupPermissions = (uint) PermissionMask.Copy,
972 NextPermissions = (uint) PermissionMask.Copy
973 };
974 invService.AddItem(itembase); 1156 invService.AddItem(itembase);
975 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); 1157 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type));
976 ScenePresence presence = null; 1158 ScenePresence presence = null;
977 if (m_scene.TryGetScenePresence(userID, out presence)) 1159 if (m_scene.TryGetScenePresence(userID, out presence))
978 { 1160 {
979 m_scene.SendInventoryUpdate(presence.ControllingClient, 1161 m_scene.SendInventoryUpdate(presence.ControllingClient,
980 invService.GetFolderForType(userID, 1162 invService.GetFolderForType(userID, FolderType.CurrentOutfit), false, true);
981 FolderType
982 .CurrentOutfit),
983 false, true);
984 } 1163 }
985 } 1164 }
986 } 1165 }
@@ -1040,7 +1219,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1040 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); 1219 m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId);
1041 }, null, "AvatarFactoryModule.OnClientRequestWearables"); 1220 }, null, "AvatarFactoryModule.OnClientRequestWearables");
1042 } 1221 }
1043 1222
1044 /// <summary> 1223 /// <summary>
1045 /// Set appearance data (texture asset IDs and slider settings) received from a client 1224 /// Set appearance data (texture asset IDs and slider settings) received from a client
1046 /// </summary> 1225 /// </summary>
@@ -1080,8 +1259,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1080 1259
1081 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 1260 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
1082 { 1261 {
1083 if (wear.Type < AvatarWearable.MAX_WEARABLES) 1262 // If the wearable type is larger than the current array, expand it
1084 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero); 1263 if (avatAppearance.Wearables.Length <= wear.Type)
1264 {
1265 int currentLength = avatAppearance.Wearables.Length;
1266 AvatarWearable[] wears = avatAppearance.Wearables;
1267 Array.Resize(ref wears, wear.Type + 1);
1268 for (int i = currentLength ; i <= wear.Type ; i++)
1269 wears[i] = new AvatarWearable();
1270 avatAppearance.Wearables = wears;
1271 }
1272 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero);
1085 } 1273 }
1086 1274
1087 avatAppearance.GetAssetsFrom(sp.Appearance); 1275 avatAppearance.GetAssetsFrom(sp.Appearance);
@@ -1117,12 +1305,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1117 { 1305 {
1118 UUID texture = UUID.Zero; 1306 UUID texture = UUID.Zero;
1119 int index = request.BakedTextureIndex; 1307 int index = request.BakedTextureIndex;
1120 1308
1121 if (m_reusetextures) 1309 if (m_reusetextures)
1122 { 1310 {
1123 // this is the most insanely dumb way to do this... however it seems to 1311 // this is the most insanely dumb way to do this... however it seems to
1124 // actually work. if the appearance has been reset because wearables have 1312 // actually work. if the appearance has been reset because wearables have
1125 // changed then the texture entries are zero'd out until the bakes are 1313 // changed then the texture entries are zero'd out until the bakes are
1126 // uploaded. on login, if the textures exist in the cache (eg if you logged 1314 // uploaded. on login, if the textures exist in the cache (eg if you logged
1127 // into the simulator recently, then the appearance will pull those and send 1315 // into the simulator recently, then the appearance will pull those and send
1128 // them back in the packet and you won't have to rebake. if the textures aren't 1316 // them back in the packet and you won't have to rebake. if the textures aren't
@@ -1138,7 +1326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1138 1326
1139 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index); 1327 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1140 } 1328 }
1141 1329
1142 CachedTextureResponseArg response = new CachedTextureResponseArg(); 1330 CachedTextureResponseArg response = new CachedTextureResponseArg();
1143 response.BakedTextureIndex = index; 1331 response.BakedTextureIndex = index;
1144 response.BakedTextureID = texture; 1332 response.BakedTextureID = texture;
@@ -1146,7 +1334,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1146 1334
1147 cachedTextureResponse.Add(response); 1335 cachedTextureResponse.Add(response);
1148 } 1336 }
1149 1337
1150 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial); 1338 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1151 // The serial number appears to be used to match requests and responses 1339 // The serial number appears to be used to match requests and responses
1152 // in the texture transaction. We just send back the serial number 1340 // in the texture transaction. We just send back the serial number
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 9513408..33489d1 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
55 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly 55 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
56 // to the AssetService, which will then store temporary and local assets permanently 56 // to the AssetService, which will then store temporary and local assets permanently
57 CoreAssetCache assetCache = new CoreAssetCache(); 57 CoreAssetCache assetCache = new CoreAssetCache();
58 58
59 AvatarFactoryModule afm = new AvatarFactoryModule(); 59 AvatarFactoryModule afm = new AvatarFactoryModule();
60 TestScene scene = new SceneHelpers(assetCache).SetupScene(); 60 TestScene scene = new SceneHelpers(assetCache).SetupScene();
61 SceneHelpers.SetupSceneModules(scene, afm); 61 SceneHelpers.SetupSceneModules(scene, afm);
@@ -63,7 +63,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
63 63
64 // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules 64 // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules
65 AssetBase bakedTextureAsset; 65 AssetBase bakedTextureAsset;
66 bakedTextureAsset 66 bakedTextureAsset
67 = new AssetBase( 67 = new AssetBase(
68 bakedTextureID, "Test Baked Texture", (sbyte)AssetType.Texture, userId.ToString()); 68 bakedTextureID, "Test Baked Texture", (sbyte)AssetType.Texture, userId.ToString());
69 bakedTextureAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet 69 bakedTextureAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet
@@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
85 // This is the alpha texture 85 // This is the alpha texture
86 eyesFace.TextureID = bakedTextureID; 86 eyesFace.TextureID = bakedTextureID;
87 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 87 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null);
88 88
89 Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); 89 Assert.That(rebakeRequestsReceived, Is.EqualTo(0));
90 90
91 AssetBase eyesBake = scene.AssetService.Get(bakedTextureID.ToString()); 91 AssetBase eyesBake = scene.AssetService.Get(bakedTextureID.ToString());
@@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
98 /// Test appearance setting where the baked texture UUID are library alpha textures. 98 /// Test appearance setting where the baked texture UUID are library alpha textures.
99 /// </summary> 99 /// </summary>
100 /// <remarks> 100 /// <remarks>
101 /// For a mesh avatar, it appears these 'baked textures' are used. So these should not trigger a request to 101 /// For a mesh avatar, it appears these 'baked textures' are used. So these should not trigger a request to
102 /// rebake. 102 /// rebake.
103 /// </remarks> 103 /// </remarks>
104 [Test] 104 [Test]
@@ -113,14 +113,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
113 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly 113 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
114 // to the AssetService, which will then store temporary and local assets permanently 114 // to the AssetService, which will then store temporary and local assets permanently
115 CoreAssetCache assetCache = new CoreAssetCache(); 115 CoreAssetCache assetCache = new CoreAssetCache();
116 116
117 AvatarFactoryModule afm = new AvatarFactoryModule(); 117 AvatarFactoryModule afm = new AvatarFactoryModule();
118 TestScene scene = new SceneHelpers(assetCache).SetupScene(); 118 TestScene scene = new SceneHelpers(assetCache).SetupScene();
119 SceneHelpers.SetupSceneModules(scene, afm); 119 SceneHelpers.SetupSceneModules(scene, afm);
120 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); 120 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
121 121
122 AssetBase libraryAsset; 122 AssetBase libraryAsset;
123 libraryAsset 123 libraryAsset
124 = new AssetBase( 124 = new AssetBase(
125 alphaTextureID, "Default Alpha Layer Texture", (sbyte)AssetType.Texture, userId.ToString()); 125 alphaTextureID, "Default Alpha Layer Texture", (sbyte)AssetType.Texture, userId.ToString());
126 libraryAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet 126 libraryAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet
@@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
142 // This is the alpha texture 142 // This is the alpha texture
143 eyesFace.TextureID = alphaTextureID; 143 eyesFace.TextureID = alphaTextureID;
144 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 144 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null);
145 145
146 Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); 146 Assert.That(rebakeRequestsReceived, Is.EqualTo(0));
147 } 147 }
148 148
@@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
158 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly 158 // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly
159 // to the AssetService, which will then store temporary and local assets permanently 159 // to the AssetService, which will then store temporary and local assets permanently
160 CoreAssetCache assetCache = new CoreAssetCache(); 160 CoreAssetCache assetCache = new CoreAssetCache();
161 161
162 AvatarFactoryModule afm = new AvatarFactoryModule(); 162 AvatarFactoryModule afm = new AvatarFactoryModule();
163 TestScene scene = new SceneHelpers(assetCache).SetupScene(); 163 TestScene scene = new SceneHelpers(assetCache).SetupScene();
164 SceneHelpers.SetupSceneModules(scene, afm); 164 SceneHelpers.SetupSceneModules(scene, afm);
@@ -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..61e461a 100644
--- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
53 private UTF8Encoding enc = new UTF8Encoding(); 53 private UTF8Encoding enc = new UTF8Encoding();
54 private string m_URL = String.Empty; 54 private string m_URL = String.Empty;
55 private static XmlSerializer m_serializer = new XmlSerializer(typeof(AssetBase)); 55 private static XmlSerializer m_serializer = new XmlSerializer(typeof(AssetBase));
56 private static bool m_enabled = false;
56 57
57 private static IServiceAuth m_Auth; 58 private static IServiceAuth m_Auth;
58 59
@@ -63,11 +64,19 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
63 return; 64 return;
64 65
65 m_URL = config.GetString("URL", String.Empty); 66 m_URL = config.GetString("URL", String.Empty);
67 if (m_URL == String.Empty)
68 return;
69
70 m_enabled = true;
71
66 m_Auth = ServiceAuth.Create(configSource, "XBakes"); 72 m_Auth = ServiceAuth.Create(configSource, "XBakes");
67 } 73 }
68 74
69 public void AddRegion(Scene scene) 75 public void AddRegion(Scene scene)
70 { 76 {
77 if (!m_enabled)
78 return;
79
71 // m_log.InfoFormat("[XBakes]: Enabled for region {0}", scene.RegionInfo.RegionName); 80 // m_log.InfoFormat("[XBakes]: Enabled for region {0}", scene.RegionInfo.RegionName);
72 m_Scene = scene; 81 m_Scene = scene;
73 82
@@ -101,8 +110,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
101 if (m_URL == String.Empty) 110 if (m_URL == String.Empty)
102 return null; 111 return null;
103 112
104 int size = 0;
105
106 using (RestClient rc = new RestClient(m_URL)) 113 using (RestClient rc = new RestClient(m_URL))
107 { 114 {
108 List<WearableCacheItem> ret = new List<WearableCacheItem>(); 115 List<WearableCacheItem> ret = new List<WearableCacheItem>();
@@ -113,35 +120,42 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
113 120
114 try 121 try
115 { 122 {
116 Stream s = rc.Request(m_Auth); 123 using(Stream s = rc.Request(m_Auth))
117
118 using (XmlTextReader sr = new XmlTextReader(s))
119 { 124 {
120 sr.ReadStartElement("BakedAppearance"); 125 using(XmlTextReader sr = new XmlTextReader(s))
121 while (sr.LocalName == "BakedTexture")
122 { 126 {
123 string sTextureIndex = sr.GetAttribute("TextureIndex"); 127 sr.ProhibitDtd = true;
124 int lTextureIndex = Convert.ToInt32(sTextureIndex); 128
125 string sCacheId = sr.GetAttribute("CacheId"); 129 sr.ReadStartElement("BakedAppearance");
126 UUID lCacheId = UUID.Zero; 130 while(sr.LocalName == "BakedTexture")
127 if (!(UUID.TryParse(sCacheId, out lCacheId)))
128 { 131 {
132 string sTextureIndex = sr.GetAttribute("TextureIndex");
133 int lTextureIndex = Convert.ToInt32(sTextureIndex);
134 string sCacheId = sr.GetAttribute("CacheId");
135 UUID lCacheId = UUID.Zero;
136 if(!(UUID.TryParse(sCacheId,out lCacheId)))
137 {
129 // ?? Nothing here 138 // ?? Nothing here
139 }
140
141 sr.ReadStartElement("BakedTexture");
142 if(sr.Name=="AssetBase")
143 {
144 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
145 ret.Add(new WearableCacheItem()
146 {
147 CacheId = lCacheId,
148 TextureIndex = (uint)lTextureIndex,
149 TextureAsset = a,
150 TextureID = a.FullID
151 });
152 sr.ReadEndElement();
153 }
130 } 154 }
131 155 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 } 156 }
140 157 return ret.ToArray();
141 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
142 } 158 }
143
144 return ret.ToArray();
145 } 159 }
146 catch (XmlException) 160 catch (XmlException)
147 { 161 {
@@ -150,11 +164,20 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
150 } 164 }
151 } 165 }
152 166
167 public void Store(UUID agentId)
168 {
169 }
170
171 public void UpdateMeshAvatar(UUID agentId)
172 {
173 }
174
153 public void Store(UUID agentId, WearableCacheItem[] data) 175 public void Store(UUID agentId, WearableCacheItem[] data)
154 { 176 {
155 if (m_URL == String.Empty) 177 if (m_URL == String.Empty)
156 return; 178 return;
157 179
180 int numberWears = 0;
158 MemoryStream reqStream; 181 MemoryStream reqStream;
159 182
160 using (MemoryStream bakeStream = new MemoryStream()) 183 using (MemoryStream bakeStream = new MemoryStream())
@@ -164,15 +187,16 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
164 187
165 for (int i = 0; i < data.Length; i++) 188 for (int i = 0; i < data.Length; i++)
166 { 189 {
167 if (data[i] != null) 190 if (data[i] != null && data[i].TextureAsset != null)
168 { 191 {
169 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); 192 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
170 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); 193 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
171 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); 194 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
172 if (data[i].TextureAsset != null) 195// if (data[i].TextureAsset != null)
173 m_serializer.Serialize(bakeWriter, data[i].TextureAsset); 196 m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
174 197
175 bakeWriter.WriteEndElement(); 198 bakeWriter.WriteEndElement();
199 numberWears++;
176 } 200 }
177 } 201 }
178 202
@@ -182,19 +206,22 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
182 reqStream = new MemoryStream(bakeStream.ToArray()); 206 reqStream = new MemoryStream(bakeStream.ToArray());
183 } 207 }
184 208
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( 209 Util.FireAndForget(
192 delegate 210 delegate
193 { 211 {
194 rc.Request(reqStream, m_Auth); 212 using(RestClient rc = new RestClient(m_URL))
195 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", data.Length, agentId); 213 {
214 rc.AddResourcePath("bakes");
215 rc.AddResourcePath(agentId.ToString());
216 rc.RequestMethod = "POST";
217
218 rc.Request(reqStream, m_Auth);
219 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", numberWears, agentId);
220 }
221 if(reqStream != null)
222 reqStream.Dispose();
196 }, null, "XBakesModule.Store" 223 }, null, "XBakesModule.Store"
197 ); 224 );
198 } 225 }
199 } 226 }
200} \ No newline at end of file 227}
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index f0b1e67..ea90185 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -45,17 +45,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
45 private static readonly ILog m_log = 45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private const int DEBUG_CHANNEL = 2147483647; 48 protected const int DEBUG_CHANNEL = 2147483647;
49 49
50 private bool m_enabled = true; 50 protected bool m_enabled = true;
51 private int m_saydistance = 20; 51 protected int m_saydistance = 20;
52 private int m_shoutdistance = 100; 52 protected int m_shoutdistance = 100;
53 private int m_whisperdistance = 10; 53 protected int m_whisperdistance = 10;
54 54 protected List<Scene> m_scenes = new List<Scene>();
55 internal object m_syncy = new object(); 55 protected List<string> FreezeCache = new List<string>();
56 56 protected string m_adminPrefix = "";
57 internal IConfig m_config; 57 protected object m_syncy = new object();
58 58 protected IConfig m_config;
59 #region ISharedRegionModule Members 59 #region ISharedRegionModule Members
60 public virtual void Initialise(IConfigSource config) 60 public virtual void Initialise(IConfigSource config)
61 { 61 {
@@ -69,21 +69,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
69 m_enabled = false; 69 m_enabled = false;
70 return; 70 return;
71 } 71 }
72 }
73 72
74 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 73 m_whisperdistance = m_config.GetInt("whisper_distance", m_whisperdistance);
75 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 74 m_saydistance = m_config.GetInt("say_distance", m_saydistance);
76 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 75 m_shoutdistance = m_config.GetInt("shout_distance", m_shoutdistance);
76 m_adminPrefix = m_config.GetString("admin_prefix", "");
77 }
77 } 78 }
78 79
79 public virtual void AddRegion(Scene scene) 80 public virtual void AddRegion(Scene scene)
80 { 81 {
81 if (!m_enabled) 82 if (!m_enabled) return;
82 return;
83 83
84 scene.EventManager.OnNewClient += OnNewClient; 84 lock (m_syncy)
85 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 85 {
86 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 86 if (!m_scenes.Contains(scene))
87 {
88 m_scenes.Add(scene);
89 scene.EventManager.OnNewClient += OnNewClient;
90 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
91 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
92 }
93 }
87 94
88 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 95 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance); 96 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -103,14 +110,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 110
104 public virtual void RemoveRegion(Scene scene) 111 public virtual void RemoveRegion(Scene scene)
105 { 112 {
106 if (!m_enabled) 113 if (!m_enabled) return;
107 return;
108 114
109 scene.EventManager.OnNewClient -= OnNewClient; 115 lock (m_syncy)
110 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 116 {
111 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 117 if (m_scenes.Contains(scene))
118 {
119 scene.EventManager.OnNewClient -= OnNewClient;
120 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
121 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
122 m_scenes.Remove(scene);
123 }
124 }
112 } 125 }
113 126
114 public virtual void Close() 127 public virtual void Close()
115 { 128 {
116 } 129 }
@@ -119,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
119 { 132 {
120 } 133 }
121 134
122 public Type ReplaceableInterface 135 public virtual Type ReplaceableInterface
123 { 136 {
124 get { return null; } 137 get { return null; }
125 } 138 }
@@ -137,7 +150,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
137 client.OnChatFromClient += OnChatFromClient; 150 client.OnChatFromClient += OnChatFromClient;
138 } 151 }
139 152
140 protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c) 153 protected virtual OSChatMessage FixPositionOfChatMessage(OSChatMessage c)
141 { 154 {
142 ScenePresence avatar; 155 ScenePresence avatar;
143 Scene scene = (Scene)c.Scene; 156 Scene scene = (Scene)c.Scene;
@@ -165,7 +178,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
165 return; 178 return;
166 } 179 }
167 180
168 DeliverChatToAvatars(ChatSourceType.Agent, c); 181 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
182 {
183 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
184 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
185 }
186 else
187 {
188 DeliverChatToAvatars(ChatSourceType.Agent, c);
189 }
169 } 190 }
170 191
171 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 192 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -179,34 +200,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
179 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 200 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
180 { 201 {
181 string fromName = c.From; 202 string fromName = c.From;
203 string fromNamePrefix = "";
182 UUID fromID = UUID.Zero; 204 UUID fromID = UUID.Zero;
183 UUID ownerID = UUID.Zero; 205 UUID ownerID = UUID.Zero;
184 UUID targetID = c.TargetUUID;
185 string message = c.Message; 206 string message = c.Message;
186 Scene scene = (Scene)c.Scene; 207 Scene scene = c.Scene as Scene;
208 UUID destination = c.Destination;
187 Vector3 fromPos = c.Position; 209 Vector3 fromPos = c.Position;
188 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); 210 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
189 211
212 bool checkParcelHide = false;
213 UUID sourceParcelID = UUID.Zero;
214 Vector3 hidePos = fromPos;
215
190 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 216 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
191 217
192 switch (sourceType) 218 if(!m_scenes.Contains(scene))
193 { 219 {
194 case ChatSourceType.Agent: 220 m_log.WarnFormat("[CHAT]: message from unkown scene {0} ignored",
195 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 221 scene.RegionInfo.RegionName);
196 fromPos = avatar.AbsolutePosition; 222 return;
197 fromName = avatar.Name; 223 }
198 fromID = c.Sender.AgentId;
199 ownerID = c.Sender.AgentId;
200 224
201 break; 225 switch (sourceType)
226 {
227 case ChatSourceType.Agent:
228 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
229 fromPos = avatar.AbsolutePosition;
230 fromName = avatar.Name;
231 fromID = c.Sender.AgentId;
232 if (avatar.IsViewerUIGod)
233 { // let gods speak to outside or things may get confusing
234 fromNamePrefix = m_adminPrefix;
235 checkParcelHide = false;
236 }
237 else
238 {
239 checkParcelHide = true;
240 }
241 destination = UUID.Zero; // Avatars cant "SayTo"
242 ownerID = c.Sender.AgentId;
202 243
203 case ChatSourceType.Object: 244 hidePos = fromPos;
204 fromID = c.SenderUUID; 245 break;
205 246
206 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 247 case ChatSourceType.Object:
207 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 248 fromID = c.SenderUUID;
208 249
209 break; 250 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
251 {
252 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
253 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
254 {
255 checkParcelHide = true;
256 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
257 }
258 }
259 break;
210 } 260 }
211 261
212 // TODO: iterate over message 262 // TODO: iterate over message
@@ -214,43 +264,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
214 message = message.Substring(0, 1000); 264 message = message.Substring(0, 1000);
215 265
216// m_log.DebugFormat( 266// m_log.DebugFormat(
217// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 267// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
218// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 268// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
219 269
220 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 270 HashSet<UUID> receiverIDs = new HashSet<UUID>();
221 271
222 if (targetID == UUID.Zero) 272 if (checkParcelHide)
223 { 273 {
224 // This should use ForEachClient, but clients don't have a position. 274 checkParcelHide = false;
225 // If camera is moved into client, then camera position can be used 275 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
226 scene.ForEachScenePresence( 276 {
227 delegate(ScenePresence presence) 277 ILandObject srcland = scene.LandChannel.GetLandObject(hidePos.X, hidePos.Y);
278 if (srcland != null && !srcland.LandData.SeeAVs)
228 { 279 {
229 if (TrySendChatMessage( 280 sourceParcelID = srcland.LandData.GlobalID;
230 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 281 checkParcelHide = true;
231 receiverIDs.Add(presence.UUID);
232 } 282 }
233 );
234 }
235 else
236 {
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 } 283 }
246 } 284 }
247 285
286 scene.ForEachScenePresence(
287 delegate(ScenePresence presence)
288 {
289 if (destination != UUID.Zero && presence.UUID != destination)
290 return;
291
292 if(presence.IsChildAgent)
293 {
294 if(checkParcelHide)
295 return;
296 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
297 ownerID, fromNamePrefix + fromName, c.Type,
298 message, sourceType, (destination != UUID.Zero)))
299 receiverIDs.Add(presence.UUID);
300 return;
301 }
302
303 ILandObject Presencecheck = scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
304 if (Presencecheck != null)
305 {
306 if (checkParcelHide)
307 {
308 if (sourceParcelID != Presencecheck.LandData.GlobalID && !presence.IsViewerUIGod)
309 return;
310 }
311 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
312 {
313 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
314 ownerID, fromNamePrefix + fromName, c.Type,
315 message, sourceType, (destination != UUID.Zero)))
316 receiverIDs.Add(presence.UUID);
317 }
318 }
319 });
320
248 scene.EventManager.TriggerOnChatToClients( 321 scene.EventManager.TriggerOnChatToClients(
249 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 322 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
250 } 323 }
251 324
252 static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); 325 static protected Vector3 CenterOfRegion = new Vector3(128, 128, 30);
253 326
254 public virtual void OnChatBroadcast(Object sender, OSChatMessage c) 327 public virtual void OnChatBroadcast(Object sender, OSChatMessage c)
255 { 328 {
256 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; 329 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return;
@@ -268,7 +341,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
268 // broadcast chat works by redistributing every incoming chat 341 // broadcast chat works by redistributing every incoming chat
269 // message to each avatar in the scene. 342 // message to each avatar in the scene.
270 string fromName = c.From; 343 string fromName = c.From;
271 344
272 UUID fromID = UUID.Zero; 345 UUID fromID = UUID.Zero;
273 UUID ownerID = UUID.Zero; 346 UUID ownerID = UUID.Zero;
274 ChatSourceType sourceType = ChatSourceType.Object; 347 ChatSourceType sourceType = ChatSourceType.Object;
@@ -280,35 +353,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
280 ownerID = c.Sender.AgentId; 353 ownerID = c.Sender.AgentId;
281 sourceType = ChatSourceType.Agent; 354 sourceType = ChatSourceType.Agent;
282 } 355 }
283 else if (c.SenderUUID != UUID.Zero) 356 else if (c.SenderUUID != UUID.Zero)
284 { 357 {
285 fromID = c.SenderUUID; 358 fromID = c.SenderUUID;
286 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 359 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
287 } 360 }
288
289 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
290 361
362 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
291 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 363 HashSet<UUID> receiverIDs = new HashSet<UUID>();
292
293 ((Scene)c.Scene).ForEachRootClient(
294 delegate(IClientAPI client)
295 {
296 // don't forward SayOwner chat from objects to
297 // non-owner agents
298 if ((c.Type == ChatTypeEnum.Owner) &&
299 (null != c.SenderObject) &&
300 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
301 return;
302 364
303 client.SendChatMessage( 365 if (c.Scene != null)
304 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, ownerID, 366 {
305 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 367 ((Scene)c.Scene).ForEachRootClient
306 368 (
307 receiverIDs.Add(client.AgentId); 369 delegate(IClientAPI client)
308 }); 370 {
309 371 // don't forward SayOwner chat from objects to
310 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 372 // non-owner agents
311 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 373 if ((c.Type == ChatTypeEnum.Owner) &&
374 (null != c.SenderObject) &&
375 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
376 return;
377
378 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
379 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
380 receiverIDs.Add(client.AgentId);
381 }
382 );
383 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
384 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
385 }
312 } 386 }
313 387
314 /// <summary> 388 /// <summary>
@@ -326,7 +400,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
326 /// <param name="type"></param> 400 /// <param name="type"></param>
327 /// <param name="message"></param> 401 /// <param name="message"></param>
328 /// <param name="src"></param> 402 /// <param name="src"></param>
329 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a 403 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
330 /// precondition</returns> 404 /// precondition</returns>
331 protected virtual bool TrySendChatMessage( 405 protected virtual bool TrySendChatMessage(
332 ScenePresence presence, Vector3 fromPos, Vector3 regionPos, 406 ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
@@ -356,15 +430,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
356 presence.ControllingClient.SendChatMessage( 430 presence.ControllingClient.SendChatMessage(
357 message, (byte) type, fromPos, fromName, 431 message, (byte) type, fromPos, fromName,
358 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); 432 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
359 433
360 return true; 434 return true;
361 } 435 }
362 436
437 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
438 public virtual void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
439 {
440 System.Threading.Timer Timer;
441 if (flags == 0)
442 {
443 FreezeCache.Add(target.ToString());
444 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
445 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
446 Timers.Add(target, Timer);
447 }
448 else
449 {
450 FreezeCache.Remove(target.ToString());
451 Timers.TryGetValue(target, out Timer);
452 Timers.Remove(target);
453 Timer.Dispose();
454 }
455 }
456
457 protected virtual void OnEndParcelFrozen(object avatar)
458 {
459 UUID target = (UUID)avatar;
460 FreezeCache.Remove(target.ToString());
461 System.Threading.Timer Timer;
462 Timers.TryGetValue(target, out Timer);
463 Timers.Remove(target);
464 Timer.Dispose();
465 }
363 #region SimulatorFeaturesRequest 466 #region SimulatorFeaturesRequest
364 467
365 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; 468 protected static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
366 469
367 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) 470 protected virtual void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
368 { 471 {
369 OSD extras = new OSDMap(); 472 OSD extras = new OSDMap();
370 if (features.ContainsKey("OpenSimExtras")) 473 if (features.ContainsKey("OpenSimExtras"))
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs
index 3018d94..5457dc3 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs
@@ -41,12 +41,13 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
43using OpenSim.Tests.Common; 43using OpenSim.Tests.Common;
44using System.Threading;
44 45
45namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests 46namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
46{ 47{
47 [TestFixture] 48 [TestFixture]
48 public class ChatModuleTests : OpenSimTestCase 49 public class ChatModuleTests : OpenSimTestCase
49 { 50 {
50 [TestFixtureSetUp] 51 [TestFixtureSetUp]
51 public void FixtureInit() 52 public void FixtureInit()
52 { 53 {
@@ -65,14 +66,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
65 } 66 }
66 67
67 private void SetupNeighbourRegions(TestScene sceneA, TestScene sceneB) 68 private void SetupNeighbourRegions(TestScene sceneA, TestScene sceneB)
68 { 69 {
69 // XXX: HTTP server is not (and should not be) necessary for this test, though it's absence makes the 70 // XXX: HTTP server is not (and should not be) necessary for this test, though it's absence makes the
70 // CapabilitiesModule complain when it can't set up HTTP endpoints. 71 // CapabilitiesModule complain when it can't set up HTTP endpoints.
71 // BaseHttpServer httpServer = new BaseHttpServer(99999); 72 BaseHttpServer httpServer = new BaseHttpServer(99999);
72 // MainServer.AddHttpServer(httpServer); 73 MainServer.AddHttpServer(httpServer);
73 // MainServer.Instance = httpServer; 74 MainServer.Instance = httpServer;
74 75
75 // We need entity transfer modules so that when sp2 logs into the east region, the region calls 76 // We need entity transfer modules so that when sp2 logs into the east region, the region calls
76 // EntityTransferModuleto set up a child agent on the west region. 77 // EntityTransferModuleto set up a child agent on the west region.
77 // XXX: However, this is not an entity transfer so is misleading. 78 // XXX: However, this is not an entity transfer so is misleading.
78 EntityTransferModule etmA = new EntityTransferModule(); 79 EntityTransferModule etmA = new EntityTransferModule();
@@ -86,7 +87,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
86 modulesConfig.Set("SimulationServices", lscm.Name); 87 modulesConfig.Set("SimulationServices", lscm.Name);
87 88
88 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 89 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
89 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, new ChatModule()); 90 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, new ChatModule());
90 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB, new ChatModule()); 91 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB, new ChatModule());
91 } 92 }
92 93
@@ -110,8 +111,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
110 Vector3 sp2Position = new Vector3(250, 128, 20); 111 Vector3 sp2Position = new Vector3(250, 128, 20);
111 112
112 SceneHelpers sh = new SceneHelpers(); 113 SceneHelpers sh = new SceneHelpers();
113 TestScene sceneWest = sh.SetupScene("sceneWest", TestHelpers.ParseTail(0x1), 1000, 1000); 114 TestScene sceneWest = sh.SetupScene("sceneWest", TestHelpers.ParseTail(0x1), 1000, 1000);
114 TestScene sceneEast = sh.SetupScene("sceneEast", TestHelpers.ParseTail(0x2), 1001, 1000); 115 TestScene sceneEast = sh.SetupScene("sceneEast", TestHelpers.ParseTail(0x2), 1001, 1000);
115 116
116 SetupNeighbourRegions(sceneWest, sceneEast); 117 SetupNeighbourRegions(sceneWest, sceneEast);
117 118
@@ -123,12 +124,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
123 // physics is irrelevant to this test. 124 // physics is irrelevant to this test.
124 sp1.Flying = true; 125 sp1.Flying = true;
125 126
126 // When sp1 logs in to sceneEast, it sets up a child agent in sceneWest and informs the sp2 client to 127 // When sp1 logs in to sceneEast, it sets up a child agent in sceneWest and informs the sp2 client to
127 // make the connection. For this test, will simplify this chain by making the connection directly. 128 // make the connection. For this test, will simplify this chain by making the connection directly.
128 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneWest, sp1Uuid); 129 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneWest, sp1Uuid);
129 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient; 130 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient;
130 131
131 sp1.AbsolutePosition = sp1Position; 132 sp1.AbsolutePosition = sp1Position;
132 133
133 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneWest, sp2Uuid); 134 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneWest, sp2Uuid);
134 TestClient sp2Client = (TestClient)sp2.ControllingClient; 135 TestClient sp2Client = (TestClient)sp2.ControllingClient;
@@ -137,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
137 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneEast, sp2Uuid); 138 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneEast, sp2Uuid);
138 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient; 139 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient;
139 140
140 sp2.AbsolutePosition = sp2Position; 141 sp2.AbsolutePosition = sp2Position;
141 142
142 // We must update the scenes in order to make the root new root agents trigger position updates in their 143 // We must update the scenes in order to make the root new root agents trigger position updates in their
143 // children. 144 // children.
@@ -146,19 +147,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
146 147
147 // Check child positions are correct. 148 // Check child positions are correct.
148 Assert.AreEqual( 149 Assert.AreEqual(
149 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z), 150 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z),
150 sp1ChildClient.SceneAgent.AbsolutePosition); 151 sp1ChildClient.SceneAgent.AbsolutePosition);
151 152
152 Assert.AreEqual( 153 Assert.AreEqual(
153 new Vector3(sp2Position.X - sceneWest.RegionInfo.RegionSizeX, sp2Position.Y, sp2Position.Z), 154 new Vector3(sp2Position.X - sceneWest.RegionInfo.RegionSizeX, sp2Position.Y, sp2Position.Z),
154 sp2ChildClient.SceneAgent.AbsolutePosition); 155 sp2ChildClient.SceneAgent.AbsolutePosition);
155 156
156 string receivedSp1ChatMessage = ""; 157 string receivedSp1ChatMessage = "";
157 string receivedSp2ChatMessage = ""; 158 string receivedSp2ChatMessage = "";
158 159
159 sp1ChildClient.OnReceivedChatMessage 160 sp1ChildClient.OnReceivedChatMessage
160 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message; 161 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message;
161 sp2ChildClient.OnReceivedChatMessage 162 sp2ChildClient.OnReceivedChatMessage
162 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message; 163 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message;
163 164
164 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage); 165 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage);
@@ -166,11 +167,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
166 167
167 sp1Position = new Vector3(30, 128, 20); 168 sp1Position = new Vector3(30, 128, 20);
168 sp1.AbsolutePosition = sp1Position; 169 sp1.AbsolutePosition = sp1Position;
170 sceneWest.Update(1);
169 sceneEast.Update(1); 171 sceneEast.Update(1);
172 Thread.Sleep(12000); // child updates are now time limited
173 sceneWest.Update(5);
174 sceneEast.Update(5);
170 175
171 // Check child position is correct. 176 // Check child position is correct.
172 Assert.AreEqual( 177 Assert.AreEqual(
173 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z), 178 new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z),
174 sp1ChildClient.SceneAgent.AbsolutePosition); 179 sp1ChildClient.SceneAgent.AbsolutePosition);
175 180
176 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage); 181 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage);
@@ -197,8 +202,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
197 Vector3 sp2Position = new Vector3(128, 6, 20); 202 Vector3 sp2Position = new Vector3(128, 6, 20);
198 203
199 SceneHelpers sh = new SceneHelpers(); 204 SceneHelpers sh = new SceneHelpers();
200 TestScene sceneNorth = sh.SetupScene("sceneNorth", TestHelpers.ParseTail(0x1), 1000, 1000); 205 TestScene sceneNorth = sh.SetupScene("sceneNorth", TestHelpers.ParseTail(0x1), 1000, 1000);
201 TestScene sceneSouth = sh.SetupScene("sceneSouth", TestHelpers.ParseTail(0x2), 1000, 1001); 206 TestScene sceneSouth = sh.SetupScene("sceneSouth", TestHelpers.ParseTail(0x2), 1000, 1001);
202 207
203 SetupNeighbourRegions(sceneNorth, sceneSouth); 208 SetupNeighbourRegions(sceneNorth, sceneSouth);
204 209
@@ -210,12 +215,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
210 // physics is irrelevant to this test. 215 // physics is irrelevant to this test.
211 sp1.Flying = true; 216 sp1.Flying = true;
212 217
213 // When sp1 logs in to sceneEast, it sets up a child agent in sceneNorth and informs the sp2 client to 218 // When sp1 logs in to sceneEast, it sets up a child agent in sceneNorth and informs the sp2 client to
214 // make the connection. For this test, will simplify this chain by making the connection directly. 219 // make the connection. For this test, will simplify this chain by making the connection directly.
215 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneSouth, sp1Uuid); 220 ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneSouth, sp1Uuid);
216 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient; 221 TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient;
217 222
218 sp1.AbsolutePosition = sp1Position; 223 sp1.AbsolutePosition = sp1Position;
219 224
220 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneSouth, sp2Uuid); 225 ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneSouth, sp2Uuid);
221 TestClient sp2Client = (TestClient)sp2.ControllingClient; 226 TestClient sp2Client = (TestClient)sp2.ControllingClient;
@@ -224,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
224 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneNorth, sp2Uuid); 229 ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneNorth, sp2Uuid);
225 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient; 230 TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient;
226 231
227 sp2.AbsolutePosition = sp2Position; 232 sp2.AbsolutePosition = sp2Position;
228 233
229 // We must update the scenes in order to make the root new root agents trigger position updates in their 234 // We must update the scenes in order to make the root new root agents trigger position updates in their
230 // children. 235 // children.
@@ -233,19 +238,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
233 238
234 // Check child positions are correct. 239 // Check child positions are correct.
235 Assert.AreEqual( 240 Assert.AreEqual(
236 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z), 241 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z),
237 sp1ChildClient.SceneAgent.AbsolutePosition); 242 sp1ChildClient.SceneAgent.AbsolutePosition);
238 243
239 Assert.AreEqual( 244 Assert.AreEqual(
240 new Vector3(sp2Position.X, sp2Position.Y + sceneSouth.RegionInfo.RegionSizeY, sp2Position.Z), 245 new Vector3(sp2Position.X, sp2Position.Y + sceneSouth.RegionInfo.RegionSizeY, sp2Position.Z),
241 sp2ChildClient.SceneAgent.AbsolutePosition); 246 sp2ChildClient.SceneAgent.AbsolutePosition);
242 247
243 string receivedSp1ChatMessage = ""; 248 string receivedSp1ChatMessage = "";
244 string receivedSp2ChatMessage = ""; 249 string receivedSp2ChatMessage = "";
245 250
246 sp1ChildClient.OnReceivedChatMessage 251 sp1ChildClient.OnReceivedChatMessage
247 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message; 252 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message;
248 sp2ChildClient.OnReceivedChatMessage 253 sp2ChildClient.OnReceivedChatMessage
249 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message; 254 += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message;
250 255
251 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage); 256 TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage);
@@ -254,16 +259,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests
254 sp1Position = new Vector3(30, 128, 20); 259 sp1Position = new Vector3(30, 128, 20);
255 sp1.AbsolutePosition = sp1Position; 260 sp1.AbsolutePosition = sp1Position;
256 sceneNorth.Update(1); 261 sceneNorth.Update(1);
262 sceneSouth.Update(1);
263 Thread.Sleep(12000); // child updates are now time limited
264 sceneNorth.Update(5);
265 sceneSouth.Update(5);
257 266
258 // Check child position is correct. 267 // Check child position is correct.
259 Assert.AreEqual( 268 Assert.AreEqual(
260 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z), 269 new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z),
261 sp1ChildClient.SceneAgent.AbsolutePosition); 270 sp1ChildClient.SceneAgent.AbsolutePosition);
262 271
263 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage); 272 TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage);
264 TestUserOutOfRange(sp2Client, "lentils", ref receivedSp1ChatMessage); 273 TestUserOutOfRange(sp2Client, "lentils", ref receivedSp1ChatMessage);
265 } 274 }
266 275
267 private void TestUserInRange(TestClient speakClient, string testMessage, ref string receivedMessage) 276 private void TestUserInRange(TestClient speakClient, string testMessage, ref string receivedMessage)
268 { 277 {
269 receivedMessage = ""; 278 receivedMessage = "";
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/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
index 764adf9..cf65c47 100644
--- a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
@@ -62,19 +62,19 @@ namespace OpenSim.Region.CoreModules.Avatars.Commands
62 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); 62 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
63 63
64 public string Name { get { return "User Commands Module"; } } 64 public string Name { get { return "User Commands Module"; } }
65 65
66 public Type ReplaceableInterface { get { return null; } } 66 public Type ReplaceableInterface { get { return null; } }
67 67
68 public void Initialise(IConfigSource source) 68 public void Initialise(IConfigSource source)
69 { 69 {
70// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE"); 70// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE");
71 } 71 }
72 72
73 public void PostInitialise() 73 public void PostInitialise()
74 { 74 {
75// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE"); 75// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE");
76 } 76 }
77 77
78 public void Close() 78 public void Close()
79 { 79 {
80// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE"); 80// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE");
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/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
index eb23e83..4a55a7e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
@@ -118,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
118 // If we're in god mode, we reverse the meaning. Offer 118 // If we're in god mode, we reverse the meaning. Offer
119 // calling card becomes "Take a calling card" for that 119 // calling card becomes "Take a calling card" for that
120 // person, no matter if they agree or not. 120 // person, no matter if they agree or not.
121 if (sp.GodLevel >= 200) 121 if (sp.IsViewerUIGod)
122 { 122 {
123 CreateCallingCard(client.AgentId, destID, UUID.Zero, true); 123 CreateCallingCard(client.AgentId, destID, UUID.Zero, true);
124 return; 124 return;
@@ -239,8 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
239 InventoryFolderBase trashFolder = 239 InventoryFolderBase trashFolder =
240 invService.GetFolderForType(client.AgentId, FolderType.Trash); 240 invService.GetFolderForType(client.AgentId, FolderType.Trash);
241 241
242 InventoryItemBase item = new InventoryItemBase(transactionID, client.AgentId); 242 InventoryItemBase item = invService.GetItem(client.AgentId, transactionID);
243 item = invService.GetItem(item);
244 243
245 if (item != null && trashFolder != null) 244 if (item != null && trashFolder != null)
246 { 245 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 08e7dd2..772485c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -167,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
167 m_Enabled = true; 167 m_Enabled = true;
168 m_log.DebugFormat("[FRIENDS MODULE]: {0} enabled.", Name); 168 m_log.DebugFormat("[FRIENDS MODULE]: {0} enabled.", Name);
169 } 169 }
170 } 170 }
171 } 171 }
172 172
173 protected virtual void InitModule(IConfigSource config) 173 protected virtual void InitModule(IConfigSource config)
@@ -247,14 +247,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
247 { 247 {
248 FriendInfo[] friends = GetFriendsFromCache(principalID); 248 FriendInfo[] friends = GetFriendsFromCache(principalID);
249 FriendInfo finfo = GetFriend(friends, friendID); 249 FriendInfo finfo = GetFriend(friends, friendID);
250 if (finfo != null) 250 if (finfo != null && finfo.TheirFlags != -1)
251 { 251 {
252 return finfo.TheirFlags; 252 return finfo.TheirFlags;
253 } 253 }
254
255 return 0; 254 return 0;
256 } 255 }
257 256
257 private void OnMakeRootAgent(ScenePresence sp)
258 {
259 if(sp.gotCrossUpdate)
260 return;
261
262 RecacheFriends(sp.ControllingClient);
263
264 lock (m_NeedsToNotifyStatus)
265 {
266 if (m_NeedsToNotifyStatus.Remove(sp.UUID))
267 {
268 // Inform the friends that this user is online. This can only be done once the client is a Root Agent.
269 StatusChange(sp.UUID, true);
270 }
271 }
272 }
273
258 private void OnNewClient(IClientAPI client) 274 private void OnNewClient(IClientAPI client)
259 { 275 {
260 client.OnInstantMessage += OnInstantMessage; 276 client.OnInstantMessage += OnInstantMessage;
@@ -262,6 +278,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
262 client.OnDenyFriendRequest += OnDenyFriendRequest; 278 client.OnDenyFriendRequest += OnDenyFriendRequest;
263 client.OnTerminateFriendship += RemoveFriendship; 279 client.OnTerminateFriendship += RemoveFriendship;
264 client.OnGrantUserRights += GrantRights; 280 client.OnGrantUserRights += GrantRights;
281 client.OnFindAgent += FindFriend;
265 282
266 // We need to cache information for child agents as well as root agents so that friend edit/move/delete 283 // 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. 284 // permissions will work across borders where both regions are on different simulators.
@@ -326,20 +343,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
326 } 343 }
327 } 344 }
328 345
329 private void OnMakeRootAgent(ScenePresence sp)
330 {
331 RecacheFriends(sp.ControllingClient);
332
333 lock (m_NeedsToNotifyStatus)
334 {
335 if (m_NeedsToNotifyStatus.Remove(sp.UUID))
336 {
337 // Inform the friends that this user is online. This can only be done once the client is a Root Agent.
338 StatusChange(sp.UUID, true);
339 }
340 }
341 }
342
343 private void OnClientLogin(IClientAPI client) 346 private void OnClientLogin(IClientAPI client)
344 { 347 {
345 UUID agentID = client.AgentId; 348 UUID agentID = client.AgentId;
@@ -358,8 +361,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
358 m_NeedsListOfOnlineFriends.Add(agentID); 361 m_NeedsListOfOnlineFriends.Add(agentID);
359 } 362 }
360 363
364 public void IsNowRoot(ScenePresence sp)
365 {
366 OnMakeRootAgent(sp);
367 }
368
361 public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) 369 public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
362 { 370 {
371 if (client == null)
372 return false;
373
363 UUID agentID = client.AgentId; 374 UUID agentID = client.AgentId;
364 375
365 // Check if the online friends list is needed 376 // Check if the online friends list is needed
@@ -500,18 +511,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
500 if (((fi.MyFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) 511 if (((fi.MyFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1))
501 friendList.Add(fi); 512 friendList.Add(fi);
502 } 513 }
503 514 if(friendList.Count > 0)
504 Util.FireAndForget( 515 {
505 delegate 516 Util.FireAndForget(
506 { 517 delegate
507// m_log.DebugFormat( 518 {
508// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", 519// m_log.DebugFormat(
509// friendList.Count, agentID, online); 520// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
510 521// friendList.Count, agentID, online);
511 // Notify about this user status 522
512 StatusNotify(friendList, agentID, online); 523 // Notify about this user status
513 }, null, "FriendsModule.StatusChange" 524 StatusNotify(friendList, agentID, online);
514 ); 525 }, null, "FriendsModule.StatusChange"
526 );
527 }
515 } 528 }
516 } 529 }
517 530
@@ -540,6 +553,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
540 // We do this regrouping so that we can efficiently send a single request rather than one for each 553 // We do this regrouping so that we can efficiently send a single request rather than one for each
541 // friend in what may be a very large friends list. 554 // friend in what may be a very large friends list.
542 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray()); 555 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray());
556 if(friendSessions == null)
557 return;
543 558
544 foreach (PresenceInfo friendSession in friendSessions) 559 foreach (PresenceInfo friendSession in friendSessions)
545 { 560 {
@@ -561,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
561 protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im) 576 protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
562 { 577 {
563 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered) 578 if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered)
564 { 579 {
565 // we got a friendship offer 580 // we got a friendship offer
566 UUID principalID = new UUID(im.fromAgentID); 581 UUID principalID = new UUID(im.fromAgentID);
567 UUID friendID = new UUID(im.toAgentID); 582 UUID friendID = new UUID(im.toAgentID);
@@ -596,7 +611,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
596 im.imSessionID = im.fromAgentID; 611 im.imSessionID = im.fromAgentID;
597 im.fromAgentName = GetFriendshipRequesterName(agentID); 612 im.fromAgentName = GetFriendshipRequesterName(agentID);
598 613
599 // Try the local sim 614 // Try the local sim
600 if (LocalFriendshipOffered(friendID, im)) 615 if (LocalFriendshipOffered(friendID, im))
601 return true; 616 return true;
602 617
@@ -639,7 +654,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
639 ccm.CreateCallingCard(client.AgentId, friendID, UUID.Zero); 654 ccm.CreateCallingCard(client.AgentId, friendID, UUID.Zero);
640 } 655 }
641 656
642 // Update the local cache. 657 // Update the local cache.
643 RecacheFriends(client); 658 RecacheFriends(client);
644 659
645 // 660 //
@@ -695,7 +710,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
695 } 710 }
696 } 711 }
697 } 712 }
698 713
699 public void RemoveFriendship(IClientAPI client, UUID exfriendID) 714 public void RemoveFriendship(IClientAPI client, UUID exfriendID)
700 { 715 {
701 if (!DeleteFriendship(client.AgentId, exfriendID)) 716 if (!DeleteFriendship(client.AgentId, exfriendID))
@@ -723,7 +738,65 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
723 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 738 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
724 m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID); 739 m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID);
725 } 740 }
726 } 741 }
742 }
743
744 public void FindFriend(IClientAPI remoteClient,UUID HunterID ,UUID PreyID)
745 {
746 UUID requester = remoteClient.AgentId;
747 if(requester != HunterID) // only allow client agent to be the hunter (?)
748 return;
749
750 FriendInfo[] friends = GetFriendsFromCache(requester);
751 if (friends.Length == 0)
752 return;
753
754 FriendInfo friend = GetFriend(friends, PreyID);
755 if (friend == null)
756 return;
757
758 if(friend.TheirFlags == -1 || (friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0)
759 return;
760
761 Scene hunterScene = (Scene)remoteClient.Scene;
762
763 if(hunterScene == null)
764 return;
765
766 // check local
767 ScenePresence sp;
768 double px;
769 double py;
770 if(hunterScene.TryGetScenePresence(PreyID, out sp))
771 {
772 if(sp == null)
773 return;
774 px = hunterScene.RegionInfo.WorldLocX + sp.AbsolutePosition.X;
775 py = hunterScene.RegionInfo.WorldLocY + sp.AbsolutePosition.Y;
776
777 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
778 return;
779 }
780
781 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { PreyID.ToString() });
782
783 if (friendSessions == null || friendSessions.Length == 0)
784 return;
785
786 PresenceInfo friendSession = friendSessions[0];
787 if (friendSession == null)
788 return;
789
790 GridRegion region = GridService.GetRegionByUUID(hunterScene.RegionInfo.ScopeID, friendSession.RegionID);
791
792 if(region == null)
793 return;
794
795 // we don't have presence location so point to a standard region center for now
796 px = region.RegionLocX + 128.0;
797 py = region.RegionLocY + 128.0;
798
799 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
727 } 800 }
728 801
729 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights) 802 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights)
@@ -745,7 +818,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
745 818
746 if (friend != null) // Found it 819 if (friend != null) // Found it
747 { 820 {
748 // Store it on the DB 821 // Store it on service
749 if (!StoreRights(requester, friendID, rights)) 822 if (!StoreRights(requester, friendID, rights))
750 { 823 {
751 remoteClient.SendAlertMessage("Unable to grant rights."); 824 remoteClient.SendAlertMessage("Unable to grant rights.");
@@ -869,28 +942,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
869 return false; 942 return false;
870 } 943 }
871 944
872 public bool LocalGrantRights(UUID userID, UUID friendID, int userFlags, int rights) 945 public bool LocalGrantRights(UUID userID, UUID friendID, int oldRights, int newRights)
873 { 946 {
874 IClientAPI friendClient = LocateClientObject(friendID); 947 IClientAPI friendClient = LocateClientObject(friendID);
875 if (friendClient != null) 948 if (friendClient != null)
876 { 949 {
877 bool onlineBitChanged = ((rights ^ userFlags) & (int)FriendRights.CanSeeOnline) != 0; 950 int changedRights = newRights ^ oldRights;
951 bool onlineBitChanged = (changedRights & (int)FriendRights.CanSeeOnline) != 0;
878 if (onlineBitChanged) 952 if (onlineBitChanged)
879 { 953 {
880 if ((rights & (int)FriendRights.CanSeeOnline) == 1) 954 if ((newRights & (int)FriendRights.CanSeeOnline) == 1)
881 friendClient.SendAgentOnline(new UUID[] { userID }); 955 friendClient.SendAgentOnline(new UUID[] { userID });
882 else 956 else
883 friendClient.SendAgentOffline(new UUID[] { userID }); 957 friendClient.SendAgentOffline(new UUID[] { userID });
884 } 958 }
885 else 959
886 { 960 if(changedRights != 0)
887 bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; 961 friendClient.SendChangeUserRights(userID, friendID, newRights);
888 if (canEditObjectsChanged)
889 friendClient.SendChangeUserRights(userID, friendID, rights);
890 }
891 962
892 // Update local cache 963 // Update local cache
893 UpdateLocalCache(userID, friendID, rights); 964 UpdateLocalCache(userID, friendID, newRights);
894 965
895 return true; 966 return true;
896 } 967 }
@@ -946,8 +1017,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
946 lock (m_Friends) 1017 lock (m_Friends)
947 { 1018 {
948 FriendInfo[] friends = GetFriendsFromCache(friendID); 1019 FriendInfo[] friends = GetFriendsFromCache(friendID);
949 FriendInfo finfo = GetFriend(friends, userID); 1020 if(friends != EMPTY_FRIENDS)
950 finfo.TheirFlags = rights; 1021 {
1022 FriendInfo finfo = GetFriend(friends, userID);
1023 if(finfo!= null)
1024 finfo.TheirFlags = rights;
1025 }
951 } 1026 }
952 } 1027 }
953 1028
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 13512a2..091b197 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -65,9 +65,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
65 protected override byte[] ProcessRequest( 65 protected override byte[] ProcessRequest(
66 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
67 { 67 {
68 StreamReader sr = new StreamReader(requestData); 68 string body;
69 string body = sr.ReadToEnd(); 69 using(StreamReader sr = new StreamReader(requestData))
70 sr.Close(); 70 body = sr.ReadToEnd();
71
71 body = body.Trim(); 72 body = body.Trim();
72 73
73 //m_log.DebugFormat("[XXX]: query String: {0}", body); 74 //m_log.DebugFormat("[XXX]: query String: {0}", body);
@@ -127,7 +128,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
127 UserAccount account = m_FriendsModule.UserAccountService.GetUserAccount(UUID.Zero, fromID); 128 UserAccount account = m_FriendsModule.UserAccountService.GetUserAccount(UUID.Zero, fromID);
128 string name = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; 129 string name = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
129 130
130 GridInstantMessage im = new GridInstantMessage(m_FriendsModule.Scene, fromID, name, toID, 131 GridInstantMessage im = new GridInstantMessage(m_FriendsModule.Scene, fromID, name, toID,
131 (byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero); 132 (byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero);
132 133
133 // !! HACK 134 // !! HACK
@@ -211,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
211 { 212 {
212 UUID fromID = UUID.Zero; 213 UUID fromID = UUID.Zero;
213 UUID toID = UUID.Zero; 214 UUID toID = UUID.Zero;
214 int rights = 0, userFlags = 0; 215 int oldRights = 0, newRights = 0;
215 216
216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) 217 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
217 return FailureResult(); 218 return FailureResult();
@@ -222,13 +223,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
222 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 223 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
223 return FailureResult(); 224 return FailureResult();
224 225
225 if (!Int32.TryParse(request["UserFlags"].ToString(), out userFlags)) 226 if (!Int32.TryParse(request["UserFlags"].ToString(), out oldRights))
226 return FailureResult(); 227 return FailureResult();
227 228
228 if (!Int32.TryParse(request["Rights"].ToString(), out rights)) 229 if (!Int32.TryParse(request["Rights"].ToString(), out newRights))
229 return FailureResult(); 230 return FailureResult();
230 231
231 if (m_FriendsModule.LocalGrantRights(UUID.Zero, UUID.Zero, userFlags, rights)) 232 if (m_FriendsModule.LocalGrantRights(fromID, toID, oldRights, newRights))
232 return SuccessResult(); 233 return SuccessResult();
233 234
234 return FailureResult(); 235 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index 27b7376..fae1e05 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
141 if (avatar == null) 141 if (avatar == null)
142 return; 142 return;
143 143
144 if (avatar.UserLevel < m_levelHGFriends) 144 if (avatar.GodController.UserLevel < m_levelHGFriends)
145 { 145 {
146 client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false); 146 client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false);
147 return; 147 return;
@@ -214,7 +214,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
214 FriendInfo[] friends = GetFriendsFromCache(client.AgentId); 214 FriendInfo[] friends = GetFriendsFromCache(client.AgentId);
215 foreach (FriendInfo f in friends) 215 foreach (FriendInfo f in friends)
216 { 216 {
217 client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); 217 int rights = f.TheirFlags;
218 if(rights != -1 )
219 client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, rights);
218 } 220 }
219 } 221 }
220 } 222 }
@@ -337,7 +339,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
337 if (UUID.TryParse(friendID, out id)) 339 if (UUID.TryParse(friendID, out id))
338 return base.FriendshipMessage(friendID); 340 return base.FriendshipMessage(friendID);
339 341
340 return "Please confirm this friendship you made while you were away."; 342 return "Please confirm this friendship you made while you where on another HG grid";
341 } 343 }
342 344
343 protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) 345 protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
@@ -456,6 +458,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
456 { 458 {
457 // local grid users 459 // local grid users
458 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); 460 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
461 DeletePreviousHGRelations(agentID, friendID);
459 base.StoreFriendships(agentID, friendID); 462 base.StoreFriendships(agentID, friendID);
460 return; 463 return;
461 } 464 }
@@ -538,8 +541,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
538 // m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", 541 // m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
539 // agentUUI, friendUUI, agentFriendService, friendFriendService); 542 // agentUUI, friendUUI, agentFriendService, friendFriendService);
540 543
541 } 544 }
542 545
543 // Delete any previous friendship relations 546 // Delete any previous friendship relations
544 DeletePreviousRelations(agentID, friendID); 547 DeletePreviousRelations(agentID, friendID);
545 548
@@ -624,6 +627,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
624 } 627 }
625 } 628 }
626 629
630 private void DeletePreviousHGRelations(UUID a1, UUID a2)
631 {
632 // Delete any previous friendship relations
633 FriendInfo[] finfos = null;
634 finfos = GetFriendsFromCache(a1);
635 if (finfos != null)
636 {
637 foreach (FriendInfo f in finfos)
638 {
639 if (f.TheirFlags == -1)
640 {
641 if (f.Friend.StartsWith(a2.ToString()))
642 {
643 FriendsService.Delete(a1, f.Friend);
644 // and also the converse
645 FriendsService.Delete(f.Friend, a1.ToString());
646 }
647 }
648 }
649 }
650
651 finfos = GetFriendsFromCache(a1);
652 if (finfos != null)
653 {
654 foreach (FriendInfo f in finfos)
655 {
656 if (f.TheirFlags == -1)
657 {
658 if (f.Friend.StartsWith(a1.ToString()))
659 {
660 FriendsService.Delete(a2, f.Friend);
661 // and also the converse
662 FriendsService.Delete(f.Friend, a2.ToString());
663 }
664 }
665 }
666 }
667 }
668
627 protected override bool DeleteFriendship(UUID agentID, UUID exfriendID) 669 protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
628 { 670 {
629 Boolean agentIsLocal = true; 671 Boolean agentIsLocal = true;
@@ -743,7 +785,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
743 m_log.DebugFormat("[HGFRIENDS MODULE]: Forwading friendship from {0} to {1} @ {2}", agentID, friendID, friendsURL); 785 m_log.DebugFormat("[HGFRIENDS MODULE]: Forwading friendship from {0} to {1} @ {2}", agentID, friendID, friendsURL);
744 GridRegion region = new GridRegion(); 786 GridRegion region = new GridRegion();
745 region.ServerURI = friendsURL; 787 region.ServerURI = friendsURL;
746 788
747 string name = im.fromAgentName; 789 string name = im.fromAgentName;
748 if (m_uMan.IsLocalGridUser(agentID)) 790 if (m_uMan.IsLocalGridUser(agentID))
749 { 791 {
@@ -775,7 +817,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
775 } 817 }
776 818
777 m_HGFriendsConnector.FriendshipOffered(region, agentID, friendID, im.message, name); 819 m_HGFriendsConnector.FriendshipOffered(region, agentID, friendID, im.message, name);
778 820
779 return true; 821 return true;
780 } 822 }
781 } 823 }
@@ -804,4 +846,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
804 return false; 846 return false;
805 } 847 }
806 } 848 }
807} \ No newline at end of file 849}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs
index 1fa4dd6..3fae271 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGStatusNotifier.cs
@@ -32,7 +32,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
32 { 32 {
33 if (kvp.Key != "local") 33 if (kvp.Key != "local")
34 { 34 {
35 // For the others, call the user agent service 35 // For the others, call the user agent service
36 List<string> ids = new List<string>(); 36 List<string> ids = new List<string>();
37 foreach (FriendInfo f in kvp.Value) 37 foreach (FriendInfo f in kvp.Value)
38 ids.Add(f.Friend); 38 ids.Add(f.Friend);
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index e6fd54e..3d9bd35 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
67 // so that different services and simulator can share the data in standalone mode. This is pretty horrible 67 // so that different services and simulator can share the data in standalone mode. This is pretty horrible
68 // effectively the statics are global variables. 68 // effectively the statics are global variables.
69 NullFriendsData.Clear(); 69 NullFriendsData.Clear();
70 70
71 IConfigSource config = new IniConfigSource(); 71 IConfigSource config = new IniConfigSource();
72 config.AddConfig("Modules"); 72 config.AddConfig("Modules");
73 // Not strictly necessary since FriendsModule assumes it is the default (!) 73 // Not strictly necessary since FriendsModule assumes it is the default (!)
diff --git a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
index 095c57b..03e2c5a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
@@ -42,11 +42,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GesturesModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GesturesModule")]
44 public class GesturesModule : INonSharedRegionModule 44 public class GesturesModule : INonSharedRegionModule
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 protected Scene m_scene; 48 protected Scene m_scene;
49 49
50 public void Initialise(IConfigSource source) 50 public void Initialise(IConfigSource source)
51 { 51 {
52 } 52 }
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
67 m_scene.EventManager.OnNewClient -= OnNewClient; 67 m_scene.EventManager.OnNewClient -= OnNewClient;
68 m_scene = null; 68 m_scene = null;
69 } 69 }
70 70
71 public void Close() {} 71 public void Close() {}
72 public string Name { get { return "Gestures Module"; } } 72 public string Name { get { return "Gestures Module"; } }
73 73
@@ -81,19 +81,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
81 client.OnActivateGesture += ActivateGesture; 81 client.OnActivateGesture += ActivateGesture;
82 client.OnDeactivateGesture += DeactivateGesture; 82 client.OnDeactivateGesture += DeactivateGesture;
83 } 83 }
84 84
85 public virtual void ActivateGesture(IClientAPI client, UUID assetId, UUID gestureId) 85 public virtual void ActivateGesture(IClientAPI client, UUID assetId, UUID gestureId)
86 { 86 {
87 IInventoryService invService = m_scene.InventoryService; 87 IInventoryService invService = m_scene.InventoryService;
88 88
89 InventoryItemBase item = new InventoryItemBase(gestureId, client.AgentId); 89 InventoryItemBase item = invService.GetItem(client.AgentId, gestureId);
90 item = invService.GetItem(item);
91 if (item != null) 90 if (item != null)
92 { 91 {
93 item.Flags |= 1; 92 item.Flags |= 1;
94 invService.UpdateItem(item); 93 invService.UpdateItem(item);
95 } 94 }
96 else 95 else
97 m_log.WarnFormat( 96 m_log.WarnFormat(
98 "[GESTURES]: Unable to find gesture {0} to activate for {1}", gestureId, client.Name); 97 "[GESTURES]: Unable to find gesture {0} to activate for {1}", gestureId, client.Name);
99 } 98 }
@@ -102,14 +101,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Gestures
102 { 101 {
103 IInventoryService invService = m_scene.InventoryService; 102 IInventoryService invService = m_scene.InventoryService;
104 103
105 InventoryItemBase item = new InventoryItemBase(gestureId, client.AgentId); 104 InventoryItemBase item = invService.GetItem(client.AgentId, gestureId);
106 item = invService.GetItem(item);
107 if (item != null) 105 if (item != null)
108 { 106 {
109 item.Flags &= ~(uint)1; 107 item.Flags &= ~(uint)1;
110 invService.UpdateItem(item); 108 invService.UpdateItem(item);
111 } 109 }
112 else 110 else
113 m_log.ErrorFormat( 111 m_log.ErrorFormat(
114 "[GESTURES]: Unable to find gesture to deactivate {0} for {1}", gestureId, client.Name); 112 "[GESTURES]: Unable to find gesture to deactivate {0} for {1}", gestureId, client.Name);
115 } 113 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 3b6d970..6e6974a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -59,19 +59,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
59 59
60 /// <summary>Special UUID for actions that apply to all agents</summary> 60 /// <summary>Special UUID for actions that apply to all agents</summary>
61 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); 61 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
62 private static readonly UUID UUID_GRID_GOD = new UUID("6571e388-6218-4574-87db-f9379718315e");
62 63
63 protected Scene m_scene; 64 protected Scene m_scene;
64 protected IDialogModule m_dialogModule; 65 protected IDialogModule m_dialogModule;
65 protected IDialogModule DialogModule
66 {
67 get
68 {
69 if (m_dialogModule == null)
70 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
71
72 return m_dialogModule;
73 }
74 }
75 66
76 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
77 { 68 {
@@ -96,6 +87,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
96 87
97 public void RegionLoaded(Scene scene) 88 public void RegionLoaded(Scene scene)
98 { 89 {
90 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
99 } 91 }
100 92
101 public void Close() {} 93 public void Close() {}
@@ -111,19 +103,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
111 client.OnGodKickUser += KickUser; 103 client.OnGodKickUser += KickUser;
112 client.OnRequestGodlikePowers += RequestGodlikePowers; 104 client.OnRequestGodlikePowers += RequestGodlikePowers;
113 } 105 }
114 106
115 public void UnsubscribeFromClientEvents(IClientAPI client) 107 public void UnsubscribeFromClientEvents(IClientAPI client)
116 { 108 {
117 client.OnGodKickUser -= KickUser; 109 client.OnGodKickUser -= KickUser;
118 client.OnRequestGodlikePowers -= RequestGodlikePowers; 110 client.OnRequestGodlikePowers -= RequestGodlikePowers;
119 } 111 }
120 112
121 private void OnRegisterCaps(UUID agentID, Caps caps) 113 private void OnRegisterCaps(UUID agentID, Caps caps)
122 { 114 {
123 string uri = "/CAPS/" + UUID.Random(); 115 string uri = "/CAPS/" + UUID.Random();
124 116
125 caps.RegisterHandler( 117 caps.RegisterHandler(
126 "UntrustedSimulatorMessage", 118 "UntrustedSimulatorMessage",
127 new RestStreamHandler("POST", uri, HandleUntrustedSimulatorMessage, "UntrustedSimulatorMessage", null)); 119 new RestStreamHandler("POST", uri, HandleUntrustedSimulatorMessage, "UntrustedSimulatorMessage", null));
128 } 120 }
129 121
@@ -146,11 +138,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
146 UUID godSessionID = userData["GodSessionID"].AsUUID(); 138 UUID godSessionID = userData["GodSessionID"].AsUUID();
147 uint kickFlags = userData["KickFlags"].AsUInteger(); 139 uint kickFlags = userData["KickFlags"].AsUInteger();
148 string reason = userData["Reason"].AsString(); 140 string reason = userData["Reason"].AsString();
141
149 ScenePresence god = m_scene.GetScenePresence(godID); 142 ScenePresence god = m_scene.GetScenePresence(godID);
150 if (god == null || god.ControllingClient.SessionId != godSessionID) 143 if (god == null || god.ControllingClient.SessionId != godSessionID)
151 return String.Empty; 144 return String.Empty;
152 145
153 KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason)); 146 KickUser(godID, agentID, kickFlags, reason);
154 } 147 }
155 else 148 else
156 { 149 {
@@ -160,59 +153,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
160 } 153 }
161 154
162 public void RequestGodlikePowers( 155 public void RequestGodlikePowers(
163 UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) 156 UUID agentID, UUID sessionID, UUID token, bool godLike)
164 { 157 {
165 ScenePresence sp = m_scene.GetScenePresence(agentID); 158 ScenePresence sp = m_scene.GetScenePresence(agentID);
159 if(sp == null || sp.IsDeleted || sp.IsNPC)
160 return;
166 161
167 if (sp != null) 162 if (sessionID != sp.ControllingClient.SessionId)
168 { 163 return;
169 if (godLike == false)
170 {
171 sp.GrantGodlikePowers(agentID, sessionID, token, godLike);
172 return;
173 }
174 164
175 // First check that this is the sim owner 165 sp.GrantGodlikePowers(token, godLike);
176 if (m_scene.Permissions.IsGod(agentID)) 166
177 { 167 if (godLike && !sp.IsViewerUIGod && m_dialogModule != null)
178 // Next we check for spoofing..... 168 m_dialogModule.SendAlertToUser(agentID, "Request for god powers denied");
179 UUID testSessionID = sp.ControllingClient.SessionId;
180 if (sessionID == testSessionID)
181 {
182 if (sessionID == controllingClient.SessionId)
183 {
184 //m_log.Info("godlike: " + godLike.ToString());
185 sp.GrantGodlikePowers(agentID, testSessionID, token, godLike);
186 }
187 }
188 }
189 else
190 {
191 if (DialogModule != null)
192 DialogModule.SendAlertToUser(agentID, "Request for god powers denied");
193 }
194 }
195 } 169 }
196 170
171 public void KickUser(UUID godID, UUID agentID, uint kickflags, byte[] reason)
172 {
173 KickUser(godID, agentID, kickflags, Utils.BytesToString(reason));
174 }
175
197 /// <summary> 176 /// <summary>
198 /// Kicks User specified from the simulator. This logs them off of the grid 177 /// Kicks or freezes User specified from the simulator. This logs them off of the grid
199 /// If the client gets the UUID: 44e87126e7944ded05b37c42da3d5cdb it assumes
200 /// that you're kicking it even if the avatar's UUID isn't the UUID that the
201 /// agent is assigned
202 /// </summary> 178 /// </summary>
203 /// <param name="godID">The person doing the kicking</param> 179 /// <param name="godID">The person doing the kicking</param>
204 /// <param name="sessionID">The session of the person doing the kicking</param>
205 /// <param name="agentID">the person that is being kicked</param> 180 /// <param name="agentID">the person that is being kicked</param>
206 /// <param name="kickflags">Tells what to do to the user</param> 181 /// <param name="kickflags">Tells what to do to the user</param>
207 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 182 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
208 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) 183 public void KickUser(UUID godID, UUID agentID, uint kickflags, string reason)
209 { 184 {
210 if (!m_scene.Permissions.IsGod(godID)) 185 // assuming automatic god rights on this for fast griefing reaction
186 // this is also needed for kick via message
187 if(!m_scene.Permissions.IsGod(godID))
211 return; 188 return;
212 189
213 ScenePresence sp = m_scene.GetScenePresence(agentID); 190 int godlevel = 200;
191 // update level so higher gods can kick lower ones
192 ScenePresence god = m_scene.GetScenePresence(godID);
193 if(god != null && god.GodController.GodLevel > godlevel)
194 godlevel = god.GodController.GodLevel;
195
196 if(agentID == ALL_AGENTS)
197 {
198 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
199 {
200 if (p.UUID != godID)
201 {
202 if(godlevel > p.GodController.GodLevel)
203 doKickmodes(godID, p, kickflags, reason);
204 else if(m_dialogModule != null)
205 m_dialogModule.SendAlertToUser(p.UUID, "Kick from " + godID.ToString() + " ignored, kick reason: " + reason);
206 }
207 });
208 return;
209 }
214 210
215 if (sp == null && agentID != ALL_AGENTS) 211 ScenePresence sp = m_scene.GetScenePresence(agentID);
212 if (sp == null || sp.IsChildAgent)
216 { 213 {
217 IMessageTransferModule transferModule = 214 IMessageTransferModule transferModule =
218 m_scene.RequestModuleInterface<IMessageTransferModule>(); 215 m_scene.RequestModuleInterface<IMessageTransferModule>();
@@ -221,58 +218,95 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
221 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID); 218 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
222 transferModule.SendInstantMessage(new GridInstantMessage( 219 transferModule.SendInstantMessage(new GridInstantMessage(
223 m_scene, godID, "God", agentID, (byte)250, false, 220 m_scene, godID, "God", agentID, (byte)250, false,
224 Utils.BytesToString(reason), UUID.Zero, true, 221 reason, UUID.Zero, true,
225 new Vector3(), new byte[] {(byte)kickflags}, true), 222 new Vector3(), new byte[] {(byte)kickflags}, true),
226 delegate(bool success) {} ); 223 delegate(bool success) {} );
227 } 224 }
228 return; 225 return;
229 } 226 }
230 227
228 if (godlevel <= sp.GodController.GodLevel) // no god wars
229 {
230 if(m_dialogModule != null)
231 m_dialogModule.SendAlertToUser(sp.UUID, "Kick from " + godID.ToString() + " ignored, kick reason: " + reason);
232 return;
233 }
234
235 if(sp.UUID == godID)
236 return;
237
238 doKickmodes(godID, sp, kickflags, reason);
239 }
240
241 private void doKickmodes(UUID godID, ScenePresence sp, uint kickflags, string reason)
242 {
231 switch (kickflags) 243 switch (kickflags)
232 { 244 {
233 case 0: 245 case 0:
234 if (sp != null) 246 KickPresence(sp, reason);
235 { 247 break;
236 KickPresence(sp, Utils.BytesToString(reason)); 248 case 1:
237 }
238 else if (agentID == ALL_AGENTS)
239 {
240 m_scene.ForEachRootScenePresence(
241 delegate(ScenePresence p)
242 {
243 if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID)))
244 KickPresence(p, Utils.BytesToString(reason));
245 }
246 );
247 }
248 break;
249 case 1:
250 if (sp != null)
251 {
252 sp.AllowMovement = false; 249 sp.AllowMovement = false;
253 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); 250 if(m_dialogModule != null)
254 m_dialogModule.SendAlertToUser(godID, "User Frozen"); 251 {
255 } 252 m_dialogModule.SendAlertToUser(sp.UUID, reason);
256 break; 253 m_dialogModule.SendAlertToUser(godID, "User Frozen");
257 case 2: 254 }
258 if (sp != null) 255 break;
259 { 256 case 2:
260 sp.AllowMovement = true; 257 sp.AllowMovement = true;
261 m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); 258 if(m_dialogModule != null)
262 m_dialogModule.SendAlertToUser(godID, "User Unfrozen"); 259 {
263 } 260 m_dialogModule.SendAlertToUser(sp.UUID, reason);
264 break; 261 m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
265 default: 262 }
266 break; 263 break;
264 default:
265 break;
267 } 266 }
268 } 267 }
269 268
270 private void KickPresence(ScenePresence sp, string reason) 269 private void KickPresence(ScenePresence sp, string reason)
271 { 270 {
272 if (sp.IsChildAgent) 271 if(sp.IsDeleted || sp.IsChildAgent)
272 return;
273 sp.ControllingClient.Kick(reason);
274 sp.Scene.CloseAgent(sp.UUID, true);
275 }
276
277 public void GridKickUser(UUID agentID, string reason)
278 {
279 int godlevel = 240; // grid god default
280
281 ScenePresence sp = m_scene.GetScenePresence(agentID);
282 if (sp == null || sp.IsChildAgent)
283 {
284 IMessageTransferModule transferModule =
285 m_scene.RequestModuleInterface<IMessageTransferModule>();
286 if (transferModule != null)
287 {
288 m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
289 transferModule.SendInstantMessage(new GridInstantMessage(
290 m_scene, UUID_GRID_GOD, "GRID", agentID, (byte)250, false,
291 reason, UUID.Zero, true,
292 new Vector3(), new byte[] {0}, true),
293 delegate(bool success) {} );
294 }
295 return;
296 }
297
298 if(sp.IsDeleted)
299 return;
300
301 if (godlevel <= sp.GodController.GodLevel) // no god wars
302 {
303 if(m_dialogModule != null)
304 m_dialogModule.SendAlertToUser(sp.UUID, "GRID kick detected and ignored, kick reason: " + reason);
273 return; 305 return;
306 }
307
274 sp.ControllingClient.Kick(reason); 308 sp.ControllingClient.Kick(reason);
275 sp.Scene.CloseAgent(sp.UUID, true); 309 sp.Scene.CloseAgent(sp.UUID, true);
276 } 310 }
277 311
278 private void OnIncomingInstantMessage(GridInstantMessage msg) 312 private void OnIncomingInstantMessage(GridInstantMessage msg)
@@ -284,7 +318,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
284 UUID godID = new UUID(msg.fromAgentID); 318 UUID godID = new UUID(msg.fromAgentID);
285 uint kickMode = (uint)msg.binaryBucket[0]; 319 uint kickMode = (uint)msg.binaryBucket[0];
286 320
287 KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason)); 321 if(godID == UUID_GRID_GOD)
322 GridKickUser(agentID, reason);
323 else
324 KickUser(godID, agentID, kickMode, reason);
288 } 325 }
289 } 326 }
290 } 327 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
index b735c61..7f91a61 100644
--- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
@@ -145,7 +145,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
145 return; 145 return;
146 146
147// m_log.Debug("[GROUPS]: Shutting down group module."); 147// m_log.Debug("[GROUPS]: Shutting down group module.");
148 148
149 lock (m_ClientMap) 149 lock (m_ClientMap)
150 { 150 {
151 m_ClientMap.Clear(); 151 m_ClientMap.Clear();
@@ -182,11 +182,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
182 m_ClientMap.Add(client.AgentId, client); 182 m_ClientMap.Add(client.AgentId, client);
183 } 183 }
184 } 184 }
185
186 GroupMembershipData[] updateGroups = new GroupMembershipData[1];
187 updateGroups[0] = osGroup;
188
189 client.SendGroupMembership(updateGroups);
190 } 185 }
191 186
192 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, 187 private void OnAgentDataUpdateRequest(IClientAPI remoteClient,
@@ -237,6 +232,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
237 remote_client.SendGroupNameReply(groupUUID, groupnamereply); 232 remote_client.SendGroupNameReply(groupUUID, groupnamereply);
238 } 233 }
239 234
235 public GroupMembershipData[] GetMembershipData(UUID agentID)
236 {
237 GroupMembershipData[] updateGroups = new GroupMembershipData[1];
238 updateGroups[0] = osGroup;
239 return updateGroups;
240 }
241
242 public GroupMembershipData GetActiveMembershipData(UUID agentID)
243 {
244 return osGroup;
245 }
246
240 private void OnClientClosed(UUID agentID, Scene scene) 247 private void OnClientClosed(UUID agentID, Scene scene)
241 { 248 {
242 lock (m_ClientMap) 249 lock (m_ClientMap)
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
index a1b918a..16e2ec3 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -144,11 +144,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
144 foreach (Scene scene in m_Scenes) 144 foreach (Scene scene in m_Scenes)
145 { 145 {
146// m_log.DebugFormat( 146// m_log.DebugFormat(
147// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}", 147// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}",
148// toAgentID.ToString(), scene.RegionInfo.RegionName); 148// toAgentID.ToString(), scene.RegionInfo.RegionName);
149 ScenePresence sp = scene.GetScenePresence(toAgentID); 149 ScenePresence sp = scene.GetScenePresence(toAgentID);
150 if (sp != null && !sp.IsChildAgent) 150 if (sp != null && !sp.IsChildAgent && !sp.IsDeleted)
151 { 151 {
152 // Local message 152 // Local message
153// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); 153// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
154 sp.ControllingClient.SendInstantMessage(im); 154 sp.ControllingClient.SendInstantMessage(im);
@@ -159,25 +159,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 } 159 }
160 } 160 }
161 161
162 // try child avatar second
163 foreach (Scene scene in m_Scenes)
164 {
165// m_log.DebugFormat(
166// "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}",
167// toAgentID, scene.RegionInfo.RegionName);
168 ScenePresence sp = scene.GetScenePresence(toAgentID);
169 if (sp != null)
170 {
171 // Local message
172// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
173 sp.ControllingClient.SendInstantMessage(im);
174
175 // Message sent
176 result(true);
177 return;
178 }
179 }
180
181// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 162// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
182 // Is the user a local user? 163 // Is the user a local user?
183 string url = string.Empty; 164 string url = string.Empty;
@@ -224,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
224 foreach (Scene scene in m_Scenes) 205 foreach (Scene scene in m_Scenes)
225 { 206 {
226 ScenePresence sp = scene.GetScenePresence(toAgentID); 207 ScenePresence sp = scene.GetScenePresence(toAgentID);
227 if(sp != null && !sp.IsChildAgent) 208 if(sp != null && !sp.IsChildAgent && !sp.IsDeleted)
228 { 209 {
229 scene.EventManager.TriggerIncomingInstantMessage(gim); 210 scene.EventManager.TriggerIncomingInstantMessage(gim);
230 successful = true; 211 successful = true;
@@ -310,7 +291,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
310 foreach (Scene scene in m_Scenes) 291 foreach (Scene scene in m_Scenes)
311 { 292 {
312 ScenePresence presence = scene.GetScenePresence(agentID); 293 ScenePresence presence = scene.GetScenePresence(agentID);
313 if (presence != null && !presence.IsChildAgent) 294 if (presence != null && !presence.IsChildAgent && !presence.IsDeleted)
314 return presence.ControllingClient; 295 return presence.ControllingClient;
315 } 296 }
316 } 297 }
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index c33a296..71c0a8a 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;
@@ -47,15 +48,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
47 /// <value> 48 /// <value>
48 /// Is this module enabled? 49 /// Is this module enabled?
49 /// </value> 50 /// </value>
50 private bool m_enabled = false; 51 protected bool m_enabled = false;
51 52
52 private readonly List<Scene> m_scenes = new List<Scene>(); 53 protected readonly List<Scene> m_scenes = new List<Scene>();
53 54
54 #region Region Module interface 55 #region Region Module interface
55 56
56 private IMessageTransferModule m_TransferModule = null; 57 protected IMessageTransferModule m_TransferModule = null;
57 58
58 public void Initialise(IConfigSource config) 59 public virtual void Initialise(IConfigSource config)
59 { 60 {
60 if (config.Configs["Messaging"] != null) 61 if (config.Configs["Messaging"] != null)
61 { 62 {
@@ -64,11 +65,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
64 "InstantMessageModule") 65 "InstantMessageModule")
65 return; 66 return;
66 } 67 }
67 68
68 m_enabled = true; 69 m_enabled = true;
69 } 70 }
70 71
71 public void AddRegion(Scene scene) 72 public virtual void AddRegion(Scene scene)
72 { 73 {
73 if (!m_enabled) 74 if (!m_enabled)
74 return; 75 return;
@@ -84,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
84 } 85 }
85 } 86 }
86 87
87 public void RegionLoaded(Scene scene) 88 public virtual void RegionLoaded(Scene scene)
88 { 89 {
89 if (!m_enabled) 90 if (!m_enabled)
90 return; 91 return;
@@ -106,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
106 } 107 }
107 } 108 }
108 109
109 public void RemoveRegion(Scene scene) 110 public virtual void RemoveRegion(Scene scene)
110 { 111 {
111 if (!m_enabled) 112 if (!m_enabled)
112 return; 113 return;
@@ -117,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
117 } 118 }
118 } 119 }
119 120
120 void OnClientConnect(IClientCore client) 121 protected virtual void OnClientConnect(IClientCore client)
121 { 122 {
122 IClientIM clientIM; 123 IClientIM clientIM;
123 if (client.TryGet(out clientIM)) 124 if (client.TryGet(out clientIM))
@@ -126,27 +127,33 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
126 } 127 }
127 } 128 }
128 129
129 public void PostInitialise() 130 public virtual void PostInitialise()
130 { 131 {
131 } 132 }
132 133
133 public void Close() 134 public virtual void Close()
134 { 135 {
135 } 136 }
136 137
137 public string Name 138 public virtual string Name
138 { 139 {
139 get { return "InstantMessageModule"; } 140 get { return "InstantMessageModule"; }
140 } 141 }
141 142
142 public Type ReplaceableInterface 143 public virtual Type ReplaceableInterface
143 { 144 {
144 get { return null; } 145 get { return null; }
145 } 146 }
146 147
147 #endregion 148 #endregion
148 149/*
149 public void OnInstantMessage(IClientAPI client, GridInstantMessage im) 150 public virtual void OnViewerInstantMessage(IClientAPI client, GridInstantMessage im)
151 {
152 im.fromAgentName = client.FirstName + " " + client.LastName;
153 OnInstantMessage(client, im);
154 }
155*/
156 public virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
150 { 157 {
151 byte dialog = im.dialog; 158 byte dialog = im.dialog;
152 159
@@ -159,10 +166,34 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 return; 166 return;
160 } 167 }
161 168
169 //DateTime dt = DateTime.UtcNow;
170
171 // Ticks from UtcNow, but make it look like local. Evil, huh?
172 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
173
174 //try
175 //{
176 // // Convert that to the PST timezone
177 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
178 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
179 //}
180 //catch
181 //{
182 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
183 //}
184
185 //// And make it look local again to fool the unix time util
186 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
187
188 // If client is null, this message comes from storage and IS offline
189 if (client != null)
190 im.offline = 0;
191
192 if (im.offline == 0)
193 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
194
162 if (m_TransferModule != null) 195 if (m_TransferModule != null)
163 { 196 {
164 if (client != null)
165 im.fromAgentName = client.FirstName + " " + client.LastName;
166 m_TransferModule.SendInstantMessage(im, 197 m_TransferModule.SendInstantMessage(im,
167 delegate(bool success) 198 delegate(bool success)
168 { 199 {
@@ -193,7 +224,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
193 /// 224 ///
194 /// </summary> 225 /// </summary>
195 /// <param name="msg"></param> 226 /// <param name="msg"></param>
196 private void OnGridInstantMessage(GridInstantMessage msg) 227 protected virtual void OnGridInstantMessage(GridInstantMessage msg)
197 { 228 {
198 // Just call the Text IM handler above 229 // Just call the Text IM handler above
199 // This event won't be raised unless we have that agent, 230 // This event won't be raised unless we have that agent,
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 2462ff8..efb9421 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,53 +139,45 @@ 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
145 IClientAPI client = null;
146
138 // Try root avatar only first 147 // Try root avatar only first
139 foreach (Scene scene in m_Scenes) 148 foreach (Scene scene in m_Scenes)
140 { 149 {
141// m_log.DebugFormat(
142// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
143// toAgentID.ToString(), scene.RegionInfo.RegionName);
144
145 ScenePresence sp = scene.GetScenePresence(toAgentID); 150 ScenePresence sp = scene.GetScenePresence(toAgentID);
146 if (sp != null && !sp.IsChildAgent) 151 if (sp != null && !sp.IsDeleted && sp.ControllingClient.IsActive)
147 { 152 {
148 // Local message 153 // actualy don't send via child agents
149// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); 154 // ims can be complex things, and not sure viewers will not mess up
150 155 if(sp.IsChildAgent)
151 sp.ControllingClient.SendInstantMessage(im); 156 continue;
152 157
153 // Message sent 158 client = sp.ControllingClient;
154 result(true); 159 if(!sp.IsChildAgent)
155 return; 160 break;
156 } 161 }
157 } 162 }
158 163
159 // try child avatar second 164 if(client != null)
160 foreach (Scene scene in m_Scenes)
161 { 165 {
162// m_log.DebugFormat( 166 // Local message
163// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 167// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
164
165 ScenePresence sp = scene.GetScenePresence(toAgentID);
166 if (sp != null)
167 {
168 // Local message
169// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
170 168
171 sp.ControllingClient.SendInstantMessage(im); 169 client.SendInstantMessage(im);
172 170
173 // Message sent 171 // Message sent
174 result(true); 172 result(true);
175 return; 173 return;
176 }
177 } 174 }
178
179// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 175// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
180 176
181 SendGridInstantMessageViaXMLRPC(im, result); 177 SendGridInstantMessageViaXMLRPC(im, result);
182 } 178 }
183 179
184 public void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result) 180 public virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
185 { 181 {
186 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; 182 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
187 183
@@ -211,10 +207,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
211 protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient) 207 protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
212 { 208 {
213 bool successful = false; 209 bool successful = false;
214 210
215 // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that 211 // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that
216 // happen here and aren't caught and log them. 212 // happen here and aren't caught and log them.
217 try 213 try
218 { 214 {
219 // various rational defaults 215 // various rational defaults
220 UUID fromAgentID = UUID.Zero; 216 UUID fromAgentID = UUID.Zero;
@@ -236,7 +232,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
236 float pos_z = 0; 232 float pos_z = 0;
237 //m_log.Info("Processing IM"); 233 //m_log.Info("Processing IM");
238 234
239
240 Hashtable requestData = (Hashtable)request.Params[0]; 235 Hashtable requestData = (Hashtable)request.Params[0];
241 // Check if it's got all the data 236 // Check if it's got all the data
242 if (requestData.ContainsKey("from_agent_id") 237 if (requestData.ContainsKey("from_agent_id")
@@ -249,6 +244,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
249 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 244 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
250 && requestData.ContainsKey("binary_bucket")) 245 && requestData.ContainsKey("binary_bucket"))
251 { 246 {
247 if (m_MessageKey != String.Empty)
248 {
249 XmlRpcResponse error_resp = new XmlRpcResponse();
250 Hashtable error_respdata = new Hashtable();
251 error_respdata["success"] = "FALSE";
252 error_resp.Value = error_respdata;
253
254 if (!requestData.Contains("message_key"))
255 return error_resp;
256 if (m_MessageKey != (string)requestData["message_key"])
257 return error_resp;
258 }
259
252 // Do the easy way of validating the UUIDs 260 // Do the easy way of validating the UUIDs
253 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 261 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
254 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 262 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -382,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
382 gim.Position = Position; 390 gim.Position = Position;
383 gim.binaryBucket = binaryBucket; 391 gim.binaryBucket = binaryBucket;
384 392
385
386 // Trigger the Instant message in the scene. 393 // Trigger the Instant message in the scene.
387 foreach (Scene scene in m_Scenes) 394 foreach (Scene scene in m_Scenes)
388 { 395 {
@@ -425,104 +432,191 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 432 return resp;
426 } 433 }
427 434
435
428 /// <summary> 436 /// <summary>
429 /// delegate for sending a grid instant message asynchronously 437 /// delegate for sending a grid instant message asynchronously
430 /// </summary> 438 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); 439 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
440
441 private class GIM {
442 public GridInstantMessage im;
443 public MessageResultNotification result;
444 };
432 445
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 446 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
447 private int numInstantMessageThreads = 0;
448
449 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
434 { 450 {
435 GridInstantMessageDelegate icon = 451 lock (pendingInstantMessages) {
436 (GridInstantMessageDelegate)iar.AsyncState; 452 if (numInstantMessageThreads >= 4) {
437 icon.EndInvoke(iar); 453 GIM gim = new GIM();
454 gim.im = im;
455 gim.result = result;
456 pendingInstantMessages.Enqueue(gim);
457 } else {
458 ++ numInstantMessageThreads;
459 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
460 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
461 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
462 }
463 }
438 } 464 }
439 465
440 466
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 467 private void GridInstantMessageCompleted(IAsyncResult iar)
442 { 468 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 469 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
444 470 d.EndInvoke(iar);
445 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
446 } 471 }
447 472
448 /// <summary> 473 /// <summary>
449 /// Internal SendGridInstantMessage over XMLRPC method. 474 /// Internal SendGridInstantMessage over XMLRPC method.
450 /// </summary> 475 /// </summary>
451 /// <remarks> 476
452 /// This is called from within a dedicated thread. 477 /// <param name="prevRegionHandle">
453 /// </remarks> 478 /// 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) 479 /// regionhandle tried
480 /// </param>
481 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
482 {
483 GIM gim;
484 do {
485 try {
486 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
487 } catch (Exception e) {
488 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
489 }
490 lock (pendingInstantMessages) {
491 if (pendingInstantMessages.Count > 0) {
492 gim = pendingInstantMessages.Dequeue();
493 im = gim.im;
494 result = gim.result;
495 } else {
496 gim = null;
497 -- numInstantMessageThreads;
498 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
499 }
500 }
501 } while (gim != null);
502 }
503
504 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
455 { 505 {
506
456 UUID toAgentID = new UUID(im.toAgentID); 507 UUID toAgentID = new UUID(im.toAgentID);
457 UUID regionID; 508 PresenceInfo upd = null;
458 bool needToLookupAgent; 509 bool lookupAgent = false;
459 510
460 lock (m_UserRegionMap) 511 lock (m_UserRegionMap)
461 needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
462
463 while (true)
464 { 512 {
465 if (needToLookupAgent) 513 if (m_UserRegionMap.ContainsKey(toAgentID))
466 { 514 {
467 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); 515 upd = new PresenceInfo();
468 516 upd.RegionID = m_UserRegionMap[toAgentID];
469 UUID foundRegionID = UUID.Zero;
470 517
471 if (presences != null) 518 // We need to compare the current regionhandle with the previous region handle
519 // or the recursive loop will never end because it will never try to lookup the agent again
520 if (prevRegionID == upd.RegionID)
472 { 521 {
473 foreach (PresenceInfo p in presences) 522 lookupAgent = true;
474 {
475 if (p.RegionID != UUID.Zero)
476 {
477 foundRegionID = p.RegionID;
478 break;
479 }
480 }
481 } 523 }
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 } 524 }
489 525 else
490 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
491 if (reginfo == null)
492 { 526 {
493 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); 527 lookupAgent = true;
494 break;
495 } 528 }
529 }
496 530
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 531
502 // If the message delivery was successful, then cache the entry. 532 // Are we needing to look-up an agent?
503 if (imresult) 533 if (lookupAgent)
534 {
535 // Non-cached user agent lookup.
536 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
537 if (presences != null && presences.Length > 0)
504 { 538 {
505 lock (m_UserRegionMap) 539 foreach (PresenceInfo p in presences)
506 { 540 {
507 m_UserRegionMap[toAgentID] = regionID; 541 if (p.RegionID != UUID.Zero)
542 {
543 upd = p;
544 break;
545 }
508 } 546 }
509 result(true);
510 return;
511 } 547 }
512 548
513 // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried 549 if (upd != null)
514 // to use a locally cached region ID. All subsequent attempts need to lookup agent details from 550 {
515 // the presence service. 551 // check if we've tried this before..
516 needToLookupAgent = true; 552 // This is one way to end the recursive loop
553 //
554 if (upd.RegionID == prevRegionID)
555 {
556 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
557 HandleUndeliverableMessage(im, result);
558 return;
559 }
560 }
561 else
562 {
563 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
564 HandleUndeliverableMessage(im, result);
565 return;
566 }
517 } 567 }
518 568
519 // If we reached this point then the message was not deliverable. Remove the bad cache entry and 569 if (upd != null)
520 // signal the delivery failure. 570 {
521 lock (m_UserRegionMap) 571 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
522 m_UserRegionMap.Remove(toAgentID); 572 upd.RegionID);
573 if (reginfo != null)
574 {
575 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
576 // Not actually used anymore, left in for compatibility
577 // Remove at next interface change
578 //
579 msgdata["region_handle"] = 0;
580 bool imresult = doIMSending(reginfo, msgdata);
581 if (imresult)
582 {
583 // IM delivery successful, so store the Agent's location in our local cache.
584 lock (m_UserRegionMap)
585 {
586 if (m_UserRegionMap.ContainsKey(toAgentID))
587 {
588 m_UserRegionMap[toAgentID] = upd.RegionID;
589 }
590 else
591 {
592 m_UserRegionMap.Add(toAgentID, upd.RegionID);
593 }
594 }
595 result(true);
596 }
597 else
598 {
599 // try again, but lookup user this time.
600 // Warning, this must call the Async version
601 // of this method or we'll be making thousands of threads
602 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
603 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
523 604
524 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); 605 // This is recursive!!!!!
525 HandleUndeliverableMessage(im, result); 606 SendGridInstantMessageViaXMLRPCAsync(im, result,
607 upd.RegionID);
608 }
609 }
610 else
611 {
612 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
613 HandleUndeliverableMessage(im, result);
614 }
615 }
616 else
617 {
618 HandleUndeliverableMessage(im, result);
619 }
526 } 620 }
527 621
528 /// <summary> 622 /// <summary>
@@ -622,8 +716,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
622 gim["position_z"] = msg.Position.Z.ToString(); 716 gim["position_z"] = msg.Position.Z.ToString();
623 gim["region_id"] = new UUID(msg.RegionID).ToString(); 717 gim["region_id"] = new UUID(msg.RegionID).ToString();
624 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 718 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
719 if (m_MessageKey != String.Empty)
720 gim["message_key"] = m_MessageKey;
625 return gim; 721 return gim;
626 } 722 }
627
628 } 723 }
629} 724}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
index 315d372..2d57193 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
@@ -118,11 +118,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
118 { 118 {
119 get { return null; } 119 get { return null; }
120 } 120 }
121 121
122 public void Close() 122 public void Close()
123 { 123 {
124 } 124 }
125 125
126 private void OnNewClient(IClientAPI client) 126 private void OnNewClient(IClientAPI client)
127 { 127 {
128 client.OnMuteListRequest += OnMuteListRequest; 128 client.OnMuteListRequest += OnMuteListRequest;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs
new file mode 100644
index 0000000..6857f35
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs
@@ -0,0 +1,229 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using System.Text;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Framework.Servers;
36using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using Mono.Addins;
40
41using OpenSim.Server.Base;
42using OpenSim.Services.Interfaces;
43
44namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MuteListModuleTst")]
47 public class MuteListModuleTst : ISharedRegionModule
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 protected bool m_Enabled = false;
53 protected List<Scene> m_SceneList = new List<Scene>();
54 protected IMuteListService m_service = null;
55
56 public void Initialise(IConfigSource config)
57 {
58 IConfig cnf = config.Configs["Messaging"];
59 if (cnf == null)
60 return;
61
62 if (cnf.GetString("MuteListModule", "None") != "MuteListModuleTst")
63 return;
64
65 m_Enabled = true;
66 }
67
68 public void AddRegion(Scene scene)
69 {
70 }
71
72 public void RegionLoaded(Scene scene)
73 {
74 if (!m_Enabled)
75 return;
76
77 IXfer xfer = scene.RequestModuleInterface<IXfer>();
78 if (xfer == null)
79 {
80 m_log.ErrorFormat("[MuteListModuleTst]: Xfer not availble in region {0}. Module Disabled", scene.Name);
81 m_Enabled = false;
82 return;
83 }
84
85 IMuteListService srv = scene.RequestModuleInterface<IMuteListService>();
86 if(srv == null)
87 {
88 m_log.ErrorFormat("[MuteListModuleTst]: MuteListService not availble in region {0}. Module Disabled", scene.Name);
89 m_Enabled = false;
90 return;
91 }
92 lock (m_SceneList)
93 {
94 if(m_service == null)
95 m_service = srv;
96 m_SceneList.Add(scene);
97 scene.EventManager.OnNewClient += OnNewClient;
98 }
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103 lock (m_SceneList)
104 {
105 if(m_SceneList.Contains(scene))
106 {
107 m_SceneList.Remove(scene);
108 scene.EventManager.OnNewClient -= OnNewClient;
109 }
110 }
111 }
112
113 public void PostInitialise()
114 {
115 if (!m_Enabled)
116 return;
117
118 m_log.Debug("[MuteListModuleTst]: enabled");
119 }
120
121 public string Name
122 {
123 get { return "MuteListModuleTst"; }
124 }
125
126 public Type ReplaceableInterface
127 {
128 get { return null; }
129 }
130
131 public void Close()
132 {
133 }
134
135 private void OnNewClient(IClientAPI client)
136 {
137 client.OnMuteListRequest += OnMuteListRequest;
138 client.OnUpdateMuteListEntry += OnUpdateMuteListEntry;
139 client.OnRemoveMuteListEntry += OnRemoveMuteListEntry;
140 }
141
142 private void OnMuteListRequest(IClientAPI client, uint crc)
143 {
144 if (!m_Enabled)
145 {
146 if(crc == 0)
147 client.SendEmpytMuteList();
148 else
149 client.SendUseCachedMuteList();
150 return;
151 }
152
153 IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
154 if (xfer == null)
155 {
156 if(crc == 0)
157 client.SendEmpytMuteList();
158 else
159 client.SendUseCachedMuteList();
160 return;
161 }
162
163 Byte[] data = m_service.MuteListRequest(client.AgentId, crc);
164 if (data == null)
165 {
166 if(crc == 0)
167 client.SendEmpytMuteList();
168 else
169 client.SendUseCachedMuteList();
170 return;
171 }
172
173 if (data.Length == 0)
174 {
175 client.SendEmpytMuteList();
176 return;
177 }
178
179 if (data.Length == 1)
180 {
181 if(crc == 0)
182 client.SendEmpytMuteList();
183 else
184 client.SendUseCachedMuteList();
185 return;
186 }
187
188 string filename = "mutes" + client.AgentId.ToString();
189 xfer.AddNewFile(filename, data);
190 client.SendMuteListUpdate(filename);
191 }
192
193 private void OnUpdateMuteListEntry(IClientAPI client, UUID muteID, string muteName, int muteType, uint muteFlags)
194 {
195 if (!m_Enabled)
196 return;
197
198 UUID agentID = client.AgentId;
199 if(muteType == 1) // agent
200 {
201 if(agentID == muteID)
202 return;
203 if(m_SceneList[0].Permissions.IsAdministrator(muteID))
204 {
205 OnMuteListRequest(client, 0);
206 return;
207 }
208 }
209
210 MuteData mute = new MuteData();
211 mute.AgentID = agentID;
212 mute.MuteID = muteID;
213 mute.MuteName = muteName;
214 mute.MuteType = muteType;
215 mute.MuteFlags = (int)muteFlags;
216 mute.Stamp = Util.UnixTimeSinceEpoch();
217
218 m_service.UpdateMute(mute);
219 }
220
221 private void OnRemoveMuteListEntry(IClientAPI client, UUID muteID, string muteName)
222 {
223 if (!m_Enabled)
224 return;
225 m_service.RemoveMute(client.AgentId, muteID, muteName);
226 }
227 }
228}
229
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 9cdb1c2..315ce1b 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -39,16 +39,25 @@ 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 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 53
47 private bool enabled = true; 54 private bool enabled = true;
55 private bool m_UseNewAvnCode = false;
48 private List<Scene> m_SceneList = new List<Scene>(); 56 private List<Scene> m_SceneList = new List<Scene>();
49 private string m_RestURL = String.Empty; 57 private string m_RestURL = String.Empty;
50 IMessageTransferModule m_TransferModule = null; 58 IMessageTransferModule m_TransferModule = null;
51 private bool m_ForwardOfflineGroupMessages = true; 59 private bool m_ForwardOfflineGroupMessages = true;
60 private Dictionary<IClientAPI, List<UUID>> m_repliesSent= new Dictionary<IClientAPI, List<UUID>>();
52 61
53 public void Initialise(IConfigSource config) 62 public void Initialise(IConfigSource config)
54 { 63 {
@@ -74,6 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
74 } 83 }
75 84
76 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages); 85 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
86 m_UseNewAvnCode = cnf.GetBoolean("UseNewAvnCode", m_UseNewAvnCode);
77 } 87 }
78 88
79 public void AddRegion(Scene scene) 89 public void AddRegion(Scene scene)
@@ -138,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
138 { 148 {
139 get { return null; } 149 get { return null; }
140 } 150 }
141 151
142 public void Close() 152 public void Close()
143 { 153 {
144 } 154 }
@@ -168,11 +178,21 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
168 private void OnNewClient(IClientAPI client) 178 private void OnNewClient(IClientAPI client)
169 { 179 {
170 client.OnRetrieveInstantMessages += RetrieveInstantMessages; 180 client.OnRetrieveInstantMessages += RetrieveInstantMessages;
181 client.OnLogout += OnClientLoggedOut;
182 }
183
184 public void OnClientLoggedOut(IClientAPI client)
185 {
186 m_repliesSent.Remove(client);
171 } 187 }
172 188
173 private void RetrieveInstantMessages(IClientAPI client) 189 private void RetrieveInstantMessages(IClientAPI client)
174 { 190 {
175 if (m_RestURL != "") 191 if (m_RestURL == String.Empty)
192 {
193 return;
194 }
195 else
176 { 196 {
177 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 197 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
178 198
@@ -180,28 +200,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
180 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 200 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
181 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 201 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
182 202
183 if (msglist == null) 203 if (msglist != null)
184 {
185 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list.");
186 return;
187 }
188
189 foreach (GridInstantMessage im in msglist)
190 { 204 {
191 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 205 foreach (GridInstantMessage im in msglist)
192 // send it directly or else the item will be given twice
193 client.SendInstantMessage(im);
194 else
195 { 206 {
196 // Send through scene event manager so all modules get a chance 207 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
197 // to look at this message before it gets delivered. 208 // send it directly or else the item will be given twice
198 // 209 client.SendInstantMessage(im);
199 // Needed for proper state management for stored group 210 else
200 // invitations 211 {
201 // 212 // Send through scene event manager so all modules get a chance
202 Scene s = FindScene(client.AgentId); 213 // to look at this message before it gets delivered.
203 if (s != null) 214 //
204 s.EventManager.TriggerIncomingInstantMessage(im); 215 // Needed for proper state management for stored group
216 // invitations
217 //
218
219 im.offline = 1;
220
221 Scene s = FindScene(client.AgentId);
222 if (s != null)
223 s.EventManager.TriggerIncomingInstantMessage(im);
224 }
205 } 225 }
206 } 226 }
207 } 227 }
@@ -213,7 +233,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
213 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 233 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
214 im.dialog != (byte)InstantMessageDialog.GroupNotice && 234 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
215 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 235 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
216 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 236 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
237 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
217 { 238 {
218 return; 239 return;
219 } 240 }
@@ -225,22 +246,73 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
225 return; 246 return;
226 } 247 }
227 248
228 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 249 if(m_UseNewAvnCode)
229 "POST", m_RestURL+"/SaveMessage/", im, 10000); 250 {
251 Scene scene = FindScene(new UUID(im.fromAgentID));
252 if (scene == null)
253 scene = m_SceneList[0];
230 254
231 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 255 UUID scopeID = scene.RegionInfo.ScopeID;
256 SendReply reply = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, SendReply>(
257 "POST", m_RestURL+"/SaveMessage/?scope=" + scopeID.ToString(), im, 20000);
258
259 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
260 {
261 IClientAPI client = FindClient(new UUID(im.fromAgentID));
262 if (client == null)
263 return;
264
265 if (string.IsNullOrEmpty(reply.Message))
266 reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved");
267
268 bool sendReply = true;
269
270 switch (reply.Disposition)
271 {
272 case 0: // Normal
273 break;
274 case 1: // Only once per user
275 if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID)))
276 sendReply = false;
277 else
278 {
279 if (!m_repliesSent.ContainsKey(client))
280 m_repliesSent[client] = new List<UUID>();
281 m_repliesSent[client].Add(new UUID(im.toAgentID));
282 }
283 break;
284 }
285
286 if (sendReply)
287 {
288 client.SendInstantMessage(new GridInstantMessage(
289 null, new UUID(im.toAgentID),
290 "System", new UUID(im.fromAgentID),
291 (byte)InstantMessageDialog.MessageFromAgent,
292 reply.Message,
293 false, new Vector3()));
294 }
295 }
296 }
297 else
232 { 298 {
233 IClientAPI client = FindClient(new UUID(im.fromAgentID)); 299 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
234 if (client == null) 300 "POST", m_RestURL+"/SaveMessage/", im, 20000);
235 return; 301
302 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
303 {
304 IClientAPI client = FindClient(new UUID(im.fromAgentID));
305 if (client == null)
306 return;
236 307
237 client.SendInstantMessage(new GridInstantMessage( 308 client.SendInstantMessage(new GridInstantMessage(
238 null, new UUID(im.toAgentID), 309 null, new UUID(im.toAgentID),
239 "System", new UUID(im.fromAgentID), 310 "System", new UUID(im.fromAgentID),
240 (byte)InstantMessageDialog.MessageFromAgent, 311 (byte)InstantMessageDialog.MessageFromAgent,
241 "User is not logged in. "+ 312 "User is not logged in. "+
242 (success ? "Message saved." : "Message not saved"), 313 (success ? "Message saved." : "Message not saved"),
243 false, new Vector3())); 314 false, new Vector3()));
315 }
244 } 316 }
245 } 317 }
246 } 318 }
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs
new file mode 100644
index 0000000..b61e848
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs
@@ -0,0 +1,239 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using System.Text;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using Mono.Addins;
38using OpenSim.Data.MySQL;
39using MySql.Data.MySqlClient;
40
41
42namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XMute")]
45 public class XMuteModule : ISharedRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 protected bool m_Enabled = true;
51 protected List<Scene> m_SceneList = new List<Scene>();
52 protected MuteTableHandler m_MuteTable;
53 protected string m_DatabaseConnect;
54
55 public void Initialise(IConfigSource config)
56 {
57 IConfig cnf = config.Configs["Messaging"];
58 if (cnf == null)
59 {
60 m_Enabled = false;
61 return;
62 }
63
64 if (cnf.GetString("MuteListModule", "None") !=
65 "XMute")
66 {
67 m_Enabled = false;
68 return;
69 }
70
71 m_DatabaseConnect = cnf.GetString("MuteDatabaseConnect", String.Empty);
72 if (m_DatabaseConnect == String.Empty)
73 {
74 m_log.Debug("[XMute]: MuteDatabaseConnect missing or empty");
75 m_Enabled = false;
76 return;
77 }
78
79 m_MuteTable = new MuteTableHandler(
80 m_DatabaseConnect, "XMute", String.Empty);
81 }
82
83 public void AddRegion(Scene scene)
84 {
85 if (!m_Enabled)
86 return;
87
88 lock (m_SceneList)
89 {
90 m_SceneList.Add(scene);
91
92 scene.EventManager.OnNewClient += OnNewClient;
93 }
94 }
95
96 public void RegionLoaded(Scene scene)
97 {
98 }
99
100 public void RemoveRegion(Scene scene)
101 {
102 if (!m_Enabled)
103 return;
104
105 lock (m_SceneList)
106 {
107 m_SceneList.Remove(scene);
108 }
109 }
110
111 public void PostInitialise()
112 {
113 if (!m_Enabled)
114 return;
115
116 m_log.Debug("[XMute]: Mute list enabled");
117 }
118
119 public string Name
120 {
121 get { return "XMuteModule"; }
122 }
123
124 public Type ReplaceableInterface
125 {
126 get { return null; }
127 }
128
129 public void Close()
130 {
131 }
132
133 private void OnNewClient(IClientAPI client)
134 {
135 client.OnMuteListRequest += OnMuteListRequest;
136 client.OnUpdateMuteListEntry += OnUpdateMuteListEntry;
137 client.OnRemoveMuteListEntry += OnRemoveMuteListEntry;
138 }
139
140 private void OnMuteListRequest(IClientAPI client, uint crc)
141 {
142 string filename = "mutes"+client.AgentId.ToString();
143
144 IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
145 if (xfer != null)
146 {
147 MuteData[] data = m_MuteTable.Get("AgentID", client.AgentId.ToString());
148 if (data == null || data.Length == 0)
149 {
150 xfer.AddNewFile(filename, new Byte[0]);
151 }
152 else
153 {
154 StringBuilder sb = new StringBuilder(1024);
155
156 foreach (MuteData d in data)
157 sb.AppendFormat("{0} {1} {2}|{3}\n",
158 d.MuteType,
159 d.MuteID.ToString(),
160 d.MuteName,
161 d.MuteFlags);
162
163 Byte[] filedata = Util.UTF8.GetBytes(sb.ToString());
164
165 uint dataCrc = Crc32.Compute(filedata);
166
167 if (dataCrc == crc)
168 {
169 client.SendUseCachedMuteList();
170 return;
171 }
172
173 xfer.AddNewFile(filename, filedata);
174 }
175
176 client.SendMuteListUpdate(filename);
177 }
178 }
179
180 private void OnUpdateMuteListEntry(IClientAPI client, UUID muteID, string muteName, int muteType, uint muteFlags)
181 {
182 MuteData mute = new MuteData();
183
184 mute.AgentID = client.AgentId;
185 mute.MuteID = muteID;
186 mute.MuteName = muteName;
187 mute.MuteType = muteType;
188 mute.MuteFlags = (int)muteFlags;
189 mute.Stamp = Util.UnixTimeSinceEpoch();
190
191 m_MuteTable.Store(mute);
192 }
193
194 private void OnRemoveMuteListEntry(IClientAPI client, UUID muteID, string muteName)
195 {
196 m_MuteTable.Delete(new string[] { "AgentID",
197 "MuteID",
198 "MuteName" },
199 new string[] { client.AgentId.ToString(),
200 muteID.ToString(),
201 muteName });
202 }
203 }
204
205 public class MuteTableHandler : MySQLGenericTableHandler<MuteData>
206 {
207 public MuteTableHandler(string conn, string realm, string m) : base(conn, realm, m)
208 {
209 }
210
211 public bool Delete(string[] fields, string[] val)
212 {
213 if (fields.Length != val.Length)
214 return false;
215
216 using (MySqlCommand cmd = new MySqlCommand())
217 {
218 string text = String.Format("delete from {0} where ", m_Realm);
219
220 List<string> terms = new List<string>();
221
222 for (int i = 0 ; i < fields.Length ; i++)
223 {
224 terms.Add(String.Format("{0} = ?{0}", fields[i]));
225 cmd.Parameters.AddWithValue("?" + fields[i], val[i]);
226 }
227
228 text += string.Join(" and ", terms.ToArray());
229
230 cmd.CommandText = text;
231
232 if (ExecuteNonQuery(cmd) > 0)
233 return true;
234 return false;
235 }
236 }
237 }
238}
239
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 4a06fd1..1e21b74 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
56 /// bumps here should be compatible. 56 /// bumps here should be compatible.
57 /// </summary> 57 /// </summary>
58 public static int MAX_MAJOR_VERSION = 1; 58 public static int MAX_MAJOR_VERSION = 1;
59 59
60 protected TarArchiveReader archive; 60 protected TarArchiveReader archive;
61 61
62 private UserAccount m_userInfo; 62 private UserAccount m_userInfo;
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
66 /// ID of this request 66 /// ID of this request
67 /// </value> 67 /// </value>
68 protected UUID m_id; 68 protected UUID m_id;
69 69
70 /// <summary> 70 /// <summary>
71 /// Do we want to merge this load with existing inventory? 71 /// Do we want to merge this load with existing inventory?
72 /// </summary> 72 /// </summary>
@@ -82,46 +82,49 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
82 /// The stream from which the inventory archive will be loaded. 82 /// The stream from which the inventory archive will be loaded.
83 /// </value> 83 /// </value>
84 private Stream m_loadStream; 84 private Stream m_loadStream;
85 85
86 /// <summary> 86 /// <summary>
87 /// Has the control file been loaded for this archive? 87 /// Has the control file been loaded for this archive?
88 /// </summary> 88 /// </summary>
89 public bool ControlFileLoaded { get; private set; } 89 public bool ControlFileLoaded { get; private set; }
90 90
91 /// <summary> 91 /// <summary>
92 /// Do we want to enforce the check. IAR versions before 0.2 and 1.1 do not guarantee this order, so we can't 92 /// Do we want to enforce the check. IAR versions before 0.2 and 1.1 do not guarantee this order, so we can't
93 /// enforce. 93 /// enforce.
94 /// </summary> 94 /// </summary>
95 public bool EnforceControlFileCheck { get; private set; } 95 public bool EnforceControlFileCheck { get; private set; }
96 96
97 protected bool m_assetsLoaded; 97 protected bool m_assetsLoaded;
98 protected bool m_inventoryNodesLoaded; 98 protected bool m_inventoryNodesLoaded;
99 99
100 protected int m_successfulAssetRestores; 100 protected int m_successfulAssetRestores;
101 protected int m_failedAssetRestores; 101 protected int m_failedAssetRestores;
102 protected int m_successfulItemRestores; 102 protected int m_successfulItemRestores;
103 103
104 /// <summary> 104 /// <summary>
105 /// Root destination folder for the IAR load. 105 /// Root destination folder for the IAR load.
106 /// </summary> 106 /// </summary>
107 protected InventoryFolderBase m_rootDestinationFolder; 107 protected InventoryFolderBase m_rootDestinationFolder;
108 108
109 /// <summary> 109 /// <summary>
110 /// Inventory nodes loaded from the iar. 110 /// Inventory nodes loaded from the iar.
111 /// </summary> 111 /// </summary>
112 protected HashSet<InventoryNodeBase> m_loadedNodes = new HashSet<InventoryNodeBase>(); 112 protected Dictionary<UUID, InventoryNodeBase> m_loadedNodes = new Dictionary<UUID, InventoryNodeBase>();
113 113
114 /// <summary> 114 /// <summary>
115 /// In order to load identically named folders, we need to keep track of the folders that we have already 115 /// In order to load identically named folders, we need to keep track of the folders that we have already
116 /// resolved. 116 /// resolved.
117 /// </summary> 117 /// </summary>
118 Dictionary <string, InventoryFolderBase> m_resolvedFolders = new Dictionary<string, InventoryFolderBase>(); 118 Dictionary <string, InventoryFolderBase> m_resolvedFolders = new Dictionary<string, InventoryFolderBase>();
119 119
120 /// <summary> 120 /// <summary>
121 /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids 121 /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids
122 /// after OSP resolution (since OSP creators are only stored in the item 122 /// after OSP resolution (since OSP creators are only stored in the item
123 /// </summary> 123 /// </summary>
124 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>(); 124 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>();
125 protected Dictionary<UUID, UUID> m_itemIDs = new Dictionary<UUID, UUID>();
126 protected List<InventoryItemBase> m_invLinks = new List<InventoryItemBase>();
127 protected Dictionary<UUID, InventoryNodeBase> m_invLinksFolders = new Dictionary<UUID, InventoryNodeBase>();
125 128
126 public InventoryArchiveReadRequest( 129 public InventoryArchiveReadRequest(
127 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge) 130 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
@@ -163,9 +166,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
163 m_invPath = invPath; 166 m_invPath = invPath;
164 m_loadStream = loadStream; 167 m_loadStream = loadStream;
165 m_module = module; 168 m_module = module;
166 169
167 // FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things 170 // FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things
168 // (I thought they weren't). We will need to bump the version number and perform this check on all 171 // (I thought they weren't). We will need to bump the version number and perform this check on all
169 // subsequent IAR versions only 172 // subsequent IAR versions only
170 ControlFileLoaded = true; 173 ControlFileLoaded = true;
171 } 174 }
@@ -181,26 +184,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
181 /// returned 184 /// returned
182 /// </returns> 185 /// </returns>
183 /// <exception cref="System.Exception">Thrown if load fails.</exception> 186 /// <exception cref="System.Exception">Thrown if load fails.</exception>
184 public HashSet<InventoryNodeBase> Execute() 187 public Dictionary<UUID,InventoryNodeBase> Execute()
185 { 188 {
186 try 189 try
187 { 190 {
188 Exception reportedException = null; 191 Exception reportedException = null;
189 192
190 string filePath = "ERROR"; 193 string filePath = "ERROR";
191 194
192 List<InventoryFolderBase> folderCandidates 195 List<InventoryFolderBase> folderCandidates
193 = InventoryArchiveUtils.FindFoldersByPath( 196 = InventoryArchiveUtils.FindFoldersByPath(
194 m_InventoryService, m_userInfo.PrincipalID, m_invPath); 197 m_InventoryService, m_userInfo.PrincipalID, m_invPath);
195 198
196 if (folderCandidates.Count == 0) 199 if (folderCandidates.Count == 0)
197 { 200 {
198 // Possibly provide an option later on to automatically create this folder if it does not exist 201 // Possibly provide an option later on to automatically create this folder if it does not exist
199 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); 202 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
200 203
201 return m_loadedNodes; 204 return m_loadedNodes;
202 } 205 }
203 206
204 m_rootDestinationFolder = folderCandidates[0]; 207 m_rootDestinationFolder = folderCandidates[0];
205 archive = new TarArchiveReader(m_loadStream); 208 archive = new TarArchiveReader(m_loadStream);
206 byte[] data; 209 byte[] data;
@@ -211,7 +214,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
211 if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 214 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
212 { 215 {
213 LoadControlFile(filePath, data); 216 LoadControlFile(filePath, data);
214 } 217 }
215 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) 218 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
216 { 219 {
217 LoadAssetFile(filePath, data); 220 LoadAssetFile(filePath, data);
@@ -221,17 +224,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
221 LoadInventoryFile(filePath, entryType, data); 224 LoadInventoryFile(filePath, entryType, data);
222 } 225 }
223 } 226 }
224 227
225 archive.Close(); 228 archive.Close();
229 LoadInventoryLinks();
226 230
227 m_log.DebugFormat( 231 m_log.DebugFormat(
228 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", 232 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
229 m_successfulAssetRestores, m_failedAssetRestores); 233 m_successfulAssetRestores, m_failedAssetRestores);
230 234
231 //Alicia: When this is called by LibraryModule or Tests, m_module will be null as event is not required 235 //Alicia: When this is called by LibraryModule or Tests, m_module will be null as event is not required
232 if(m_module != null) 236 if(m_module != null)
233 m_module.TriggerInventoryArchiveLoaded(m_id, true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores); 237 m_module.TriggerInventoryArchiveLoaded(m_id, true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores);
234 238
235 return m_loadedNodes; 239 return m_loadedNodes;
236 } 240 }
237 catch(Exception Ex) 241 catch(Exception Ex)
@@ -268,36 +272,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
268 /// </param> 272 /// </param>
269 /// <returns>The last user inventory folder created or found for the archive path</returns> 273 /// <returns>The last user inventory folder created or found for the archive path</returns>
270 public InventoryFolderBase ReplicateArchivePathToUserInventory( 274 public InventoryFolderBase ReplicateArchivePathToUserInventory(
271 string iarPath, 275 string iarPath,
272 InventoryFolderBase rootDestFolder, 276 InventoryFolderBase rootDestFolder,
273 Dictionary <string, InventoryFolderBase> resolvedFolders, 277 Dictionary <string, InventoryFolderBase> resolvedFolders,
274 HashSet<InventoryNodeBase> loadedNodes) 278 Dictionary<UUID, InventoryNodeBase> loadedNodes)
275 { 279 {
276 string iarPathExisting = iarPath; 280 string iarPathExisting = iarPath;
277 281
278// m_log.DebugFormat( 282// m_log.DebugFormat(
279// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); 283// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
280 284
281 InventoryFolderBase destFolder 285 InventoryFolderBase destFolder
282 = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders); 286 = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders);
283 287
284// m_log.DebugFormat( 288// m_log.DebugFormat(
285// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", 289// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
286// iarPath, iarPathExisting); 290// iarPath, iarPathExisting);
287 291
288 string iarPathToCreate = iarPath.Substring(iarPathExisting.Length); 292 string iarPathToCreate = iarPath.Substring(iarPathExisting.Length);
289 CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes); 293 CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes);
290 294
291 return destFolder; 295 return destFolder;
292 } 296 }
293 297
294 /// <summary> 298 /// <summary>
295 /// Resolve a destination folder 299 /// Resolve a destination folder
296 /// </summary> 300 /// </summary>
297 /// 301 ///
298 /// We require here a root destination folder (usually the root of the user's inventory) and the archive 302 /// We require here a root destination folder (usually the root of the user's inventory) and the archive
299 /// path. We also pass in a list of previously resolved folders in case we've found this one previously. 303 /// path. We also pass in a list of previously resolved folders in case we've found this one previously.
300 /// 304 ///
301 /// <param name="archivePath"> 305 /// <param name="archivePath">
302 /// The item archive path to resolve. The portion of the path passed back is that 306 /// The item archive path to resolve. The portion of the path passed back is that
303 /// which corresponds to the resolved desintation folder. 307 /// which corresponds to the resolved desintation folder.
@@ -321,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
321 while (archivePath.Length > 0) 325 while (archivePath.Length > 0)
322 { 326 {
323// m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath); 327// m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
324 328
325 if (resolvedFolders.ContainsKey(archivePath)) 329 if (resolvedFolders.ContainsKey(archivePath))
326 { 330 {
327// m_log.DebugFormat( 331// m_log.DebugFormat(
@@ -332,13 +336,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
332 { 336 {
333 if (m_merge) 337 if (m_merge)
334 { 338 {
335 // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the 339 // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the
336 // iar name and try to find that instead. 340 // iar name and try to find that instead.
337 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); 341 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
338 List<InventoryFolderBase> folderCandidates 342 List<InventoryFolderBase> folderCandidates
339 = InventoryArchiveUtils.FindFoldersByPath( 343 = InventoryArchiveUtils.FindFoldersByPath(
340 m_InventoryService, m_userInfo.PrincipalID, plainPath); 344 m_InventoryService, m_userInfo.PrincipalID, plainPath);
341 345
342 if (folderCandidates.Count != 0) 346 if (folderCandidates.Count != 0)
343 { 347 {
344 InventoryFolderBase destFolder = folderCandidates[0]; 348 InventoryFolderBase destFolder = folderCandidates[0];
@@ -346,7 +350,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
346 return destFolder; 350 return destFolder;
347 } 351 }
348 } 352 }
349 353
350 // Don't include the last slash so find the penultimate one 354 // Don't include the last slash so find the penultimate one
351 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); 355 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
352 356
@@ -365,10 +369,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
365 } 369 }
366 } 370 }
367 } 371 }
368 372
369 return rootDestFolder; 373 return rootDestFolder;
370 } 374 }
371 375
372 /// <summary> 376 /// <summary>
373 /// Create a set of folders for the given path. 377 /// Create a set of folders for the given path.
374 /// </summary> 378 /// </summary>
@@ -388,11 +392,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
388 /// Track the inventory nodes created. 392 /// Track the inventory nodes created.
389 /// </param> 393 /// </param>
390 protected void CreateFoldersForPath( 394 protected void CreateFoldersForPath(
391 InventoryFolderBase destFolder, 395 InventoryFolderBase destFolder,
392 string iarPathExisting, 396 string iarPathExisting,
393 string iarPathToReplicate, 397 string iarPathToReplicate,
394 Dictionary <string, InventoryFolderBase> resolvedFolders, 398 Dictionary <string, InventoryFolderBase> resolvedFolders,
395 HashSet<InventoryNodeBase> loadedNodes) 399 Dictionary<UUID, InventoryNodeBase> loadedNodes)
396 { 400 {
397 string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 401 string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
398 402
@@ -402,7 +406,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
402 406
403 if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR)) 407 if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
404 continue; 408 continue;
405 409
406 int identicalNameIdentifierIndex 410 int identicalNameIdentifierIndex
407 = rawDirsToCreate[i].LastIndexOf( 411 = rawDirsToCreate[i].LastIndexOf(
408 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); 412 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
@@ -412,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
412 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName); 416 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
413 UUID newFolderId = UUID.Random(); 417 UUID newFolderId = UUID.Random();
414 418
415 destFolder 419 destFolder
416 = new InventoryFolderBase( 420 = new InventoryFolderBase(
417 newFolderId, newFolderName, m_userInfo.PrincipalID, 421 newFolderId, newFolderName, m_userInfo.PrincipalID,
418 (short)FolderType.None, destFolder.ID, 1); 422 (short)FolderType.None, destFolder.ID, 1);
@@ -424,10 +428,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
424 resolvedFolders[iarPathExisting] = destFolder; 428 resolvedFolders[iarPathExisting] = destFolder;
425 429
426 if (0 == i) 430 if (0 == i)
427 loadedNodes.Add(destFolder); 431 loadedNodes[destFolder.ID] = destFolder;
428 } 432 }
429 } 433 }
430 434
431 /// <summary> 435 /// <summary>
432 /// Load an item from the archive 436 /// Load an item from the archive
433 /// </summary> 437 /// </summary>
@@ -438,15 +442,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
438 protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder) 442 protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder)
439 { 443 {
440 InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data); 444 InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data);
441 445
446 UUID oldID = item.ID;
442 // Don't use the item ID that's in the file 447 // Don't use the item ID that's in the file
443 item.ID = UUID.Random(); 448 item.ID = UUID.Random();
449 m_itemIDs[oldID] = item.ID;
444 450
445 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService); 451 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService);
446 if (UUID.Zero != ospResolvedId) // The user exists in this grid 452 if (UUID.Zero != ospResolvedId) // The user exists in this grid
447 { 453 {
448// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); 454// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId);
449 455
450// item.CreatorIdAsUuid = ospResolvedId; 456// item.CreatorIdAsUuid = ospResolvedId;
451 457
452 // Don't preserve the OSPA in the creator id (which actually gets persisted to the 458 // Don't preserve the OSPA in the creator id (which actually gets persisted to the
@@ -457,7 +463,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
457 else if (string.IsNullOrEmpty(item.CreatorData)) 463 else if (string.IsNullOrEmpty(item.CreatorData))
458 { 464 {
459 item.CreatorId = m_userInfo.PrincipalID.ToString(); 465 item.CreatorId = m_userInfo.PrincipalID.ToString();
460// item.CreatorIdAsUuid = new UUID(item.CreatorId);
461 } 466 }
462 467
463 item.Owner = m_userInfo.PrincipalID; 468 item.Owner = m_userInfo.PrincipalID;
@@ -470,11 +475,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
470 // FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger 475 // FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger
471 // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than 476 // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than
472 // relying on native tar tools. 477 // relying on native tar tools.
473 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; 478 if(item.AssetType == (int)AssetType.Link)
479 {
480 m_invLinks.Add(item);
481 if(!m_loadedNodes.ContainsKey(item.Folder) && !m_invLinksFolders.ContainsKey(item.Folder))
482 m_invLinksFolders[item.Folder] = loadFolder;
483 return null;
484 }
485 else
486 {
487 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
488 if (!m_InventoryService.AddItem(item))
489 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
490 }
474 491
475 if (!m_InventoryService.AddItem(item))
476 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
477
478 return item; 492 return item;
479 } 493 }
480 494
@@ -504,56 +518,57 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
504 string rawUuid = filename.Remove(filename.Length - extension.Length); 518 string rawUuid = filename.Remove(filename.Length - extension.Length);
505 UUID assetId = new UUID(rawUuid); 519 UUID assetId = new UUID(rawUuid);
506 520
507 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) 521 if (!ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
508 { 522 {
509 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; 523 m_log.ErrorFormat(
524 "[INVENTORY ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
525 assetPath, extension);
526 return false;
527 }
510 528
511 if (assetType == (sbyte)AssetType.Unknown) 529 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
512 { 530 if (assetType == (sbyte)AssetType.Unknown)
513 m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId); 531 {
514 } 532 m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId);
515 else if (assetType == (sbyte)AssetType.Object) 533 return false;
516 { 534 }
517 if (m_creatorIdForAssetId.ContainsKey(assetId)) 535
536 if(assetType == (sbyte)AssetType.Object)
537 {
538 UUID owner = m_userInfo.PrincipalID;
539 bool doCreatorID = m_creatorIdForAssetId.ContainsKey(assetId);
540
541 data = SceneObjectSerializer.ModifySerializedObject(assetId, data,
542 sog =>
518 { 543 {
519 data = SceneObjectSerializer.ModifySerializedObject(assetId, data, 544 foreach(SceneObjectPart sop in sog.Parts)
520 sog => { 545 {
521 bool modified = false; 546 sop.OwnerID = owner;
522 547 if(doCreatorID && string.IsNullOrEmpty(sop.CreatorData))
523 foreach (SceneObjectPart sop in sog.Parts) 548 sop.CreatorID = m_creatorIdForAssetId[assetId];
524 { 549
525 if (string.IsNullOrEmpty(sop.CreatorData)) 550 foreach(TaskInventoryItem it in sop.Inventory.GetInventoryItems())
526 { 551 {
527 sop.CreatorID = m_creatorIdForAssetId[assetId]; 552 it.OwnerID = owner;
528 modified = true; 553 if(string.IsNullOrEmpty(it.CreatorData) && m_creatorIdForAssetId.ContainsKey(it.AssetID))
529 } 554 it.CreatorID = m_creatorIdForAssetId[it.AssetID];
530 } 555 }
531 556 }
532 return modified; 557 return true;
533 }); 558 });
534
535 if (data == null)
536 return false;
537 }
538 }
539 559
540 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); 560 if(data == null)
561 return false;
562 }
541 563
542 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString()); 564 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
543 asset.Data = data;
544 565
545 m_AssetService.Store(asset); 566 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
567 asset.Data = data;
546 568
547 return true; 569 m_AssetService.Store(asset);
548 }
549 else
550 {
551 m_log.ErrorFormat(
552 "[INVENTORY ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
553 assetPath, extension);
554 570
555 return false; 571 return true;
556 }
557 } 572 }
558 573
559 /// <summary> 574 /// <summary>
@@ -568,7 +583,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
568 int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value); 583 int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value);
569 int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); 584 int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value);
570 string version = string.Format("{0}.{1}", majorVersion, minorVersion); 585 string version = string.Format("{0}.{1}", majorVersion, minorVersion);
571 586
572 if (majorVersion > MAX_MAJOR_VERSION) 587 if (majorVersion > MAX_MAJOR_VERSION)
573 { 588 {
574 throw new Exception( 589 throw new Exception(
@@ -576,38 +591,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
576 "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below", 591 "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below",
577 majorVersion, MAX_MAJOR_VERSION)); 592 majorVersion, MAX_MAJOR_VERSION));
578 } 593 }
579 594
580 ControlFileLoaded = true; 595 ControlFileLoaded = true;
581 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); 596 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version);
582 } 597 }
583 598
584 /// <summary> 599 /// <summary>
585 /// Load inventory file 600 /// Load inventory file
586 /// </summary> 601 /// </summary>
587 /// <param name="path"></param> 602 /// <param name="path"></param>
588 /// <param name="entryType"></param> 603 /// <param name="entryType"></param>
589 /// <param name="data"></param> 604 /// <param name="data"></param>
590 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data) 605 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data)
591 { 606 {
592 if (!ControlFileLoaded) 607 if (!ControlFileLoaded)
593 throw new Exception( 608 throw new Exception(
594 string.Format( 609 string.Format(
595 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 610 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
596 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH)); 611 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH));
597 612
598 if (m_assetsLoaded) 613 if (m_assetsLoaded)
599 throw new Exception( 614 throw new Exception(
600 string.Format( 615 string.Format(
601 "The IAR you are trying to load does not list all {0} before {1}. Aborting load", 616 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
602 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); 617 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH));
603 618
604 path = path.Substring(ArchiveConstants.INVENTORY_PATH.Length); 619 path = path.Substring(ArchiveConstants.INVENTORY_PATH.Length);
605 620
606 // Trim off the file portion if we aren't already dealing with a directory path 621 // Trim off the file portion if we aren't already dealing with a directory path
607 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) 622 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
608 path = path.Remove(path.LastIndexOf("/") + 1); 623 path = path.Remove(path.LastIndexOf("/") + 1);
609 624
610 InventoryFolderBase foundFolder 625 InventoryFolderBase foundFolder
611 = ReplicateArchivePathToUserInventory( 626 = ReplicateArchivePathToUserInventory(
612 path, m_rootDestinationFolder, m_resolvedFolders, m_loadedNodes); 627 path, m_rootDestinationFolder, m_resolvedFolders, m_loadedNodes);
613 628
@@ -618,17 +633,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
618 if (item != null) 633 if (item != null)
619 { 634 {
620 m_successfulItemRestores++; 635 m_successfulItemRestores++;
621 636
622 // If we aren't loading the folder containing the item then well need to update the 637 // If we aren't loading the folder containing the item then well need to update the
623 // viewer separately for that item. 638 // viewer separately for that item.
624 if (!m_loadedNodes.Contains(foundFolder)) 639 if (!m_loadedNodes.ContainsKey(foundFolder.ID))
625 m_loadedNodes.Add(item); 640 m_loadedNodes[foundFolder.ID] = item;
641 }
642 }
643
644 m_inventoryNodesLoaded = true;
645 }
646
647 private void LoadInventoryLinks()
648 {
649 foreach(InventoryItemBase it in m_invLinks)
650 {
651 UUID target = it.AssetID;
652 if(m_itemIDs.ContainsKey(target))
653 {
654 it.AssetID = m_itemIDs[target];
655 if(!m_InventoryService.AddItem(it))
656 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}",it.Name,it.Folder);
657 else
658 {
659 m_successfulItemRestores++;
660 UUID fid = it.Folder;
661 if (!m_loadedNodes.ContainsKey(fid) && m_invLinksFolders.ContainsKey(fid))
662 m_loadedNodes[fid] = m_invLinksFolders[fid];
663 }
626 } 664 }
627 } 665 }
628 666
629 m_inventoryNodesLoaded = true; 667 m_itemIDs.Clear();
668 m_invLinks.Clear();
669 m_invLinksFolders.Clear();
630 } 670 }
631
632 /// <summary> 671 /// <summary>
633 /// Load asset file 672 /// Load asset file
634 /// </summary> 673 /// </summary>
@@ -639,15 +678,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
639 if (!ControlFileLoaded) 678 if (!ControlFileLoaded)
640 throw new Exception( 679 throw new Exception(
641 string.Format( 680 string.Format(
642 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 681 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
643 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH)); 682 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH));
644 683
645 if (!m_inventoryNodesLoaded) 684 if (!m_inventoryNodesLoaded)
646 throw new Exception( 685 throw new Exception(
647 string.Format( 686 string.Format(
648 "The IAR you are trying to load does not list all {0} before {1}. Aborting load", 687 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
649 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); 688 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH));
650 689
651 if (LoadAsset(path, data)) 690 if (LoadAsset(path, data))
652 m_successfulAssetRestores++; 691 m_successfulAssetRestores++;
653 else 692 else
@@ -655,10 +694,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
655 694
656 if ((m_successfulAssetRestores) % 50 == 0) 695 if ((m_successfulAssetRestores) % 50 == 0)
657 m_log.DebugFormat( 696 m_log.DebugFormat(
658 "[INVENTORY ARCHIVER]: Loaded {0} assets...", 697 "[INVENTORY ARCHIVER]: Loaded {0} assets...",
659 m_successfulAssetRestores); 698 m_successfulAssetRestores);
660 699
661 m_assetsLoaded = true; 700 m_assetsLoaded = true;
662 } 701 }
663 } 702 }
664} 703}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
index dbaf2aa..b66aad5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
69 /// The path to the required folder. 69 /// The path to the required folder.
70 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. 70 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
71 /// </param> 71 /// </param>
72 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an 72 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an
73 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns> 73 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns>
74 public static InventoryFolderBase FindFolderByPath( 74 public static InventoryFolderBase FindFolderByPath(
75 IInventoryService inventoryService, UUID userId, string path) 75 IInventoryService inventoryService, UUID userId, string path)
@@ -102,7 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
102 /// The path to the required folder. 102 /// The path to the required folder.
103 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. 103 /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
104 /// </param> 104 /// </param>
105 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an 105 /// <returns>The folder found. Please note that if there are multiple folders with the same name then an
106 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns> 106 /// unspecified one will be returned. If no such folder eixsts then null is returned</returns>
107 public static InventoryFolderBase FindFolderByPath( 107 public static InventoryFolderBase FindFolderByPath(
108 IInventoryService inventoryService, InventoryFolderBase startFolder, string path) 108 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
@@ -149,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
149 149
150 return FindFoldersByPath(inventoryService, rootFolder, path); 150 return FindFoldersByPath(inventoryService, rootFolder, path);
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// Find a set of folders given a PATH_DELIMITER delimited path starting from this folder 154 /// Find a set of folders given a PATH_DELIMITER delimited path starting from this folder
155 /// </summary> 155 /// </summary>
@@ -175,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
175 IInventoryService inventoryService, InventoryFolderBase startFolder, string path) 175 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
176 { 176 {
177 List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>(); 177 List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>();
178 178
179 if (path == string.Empty) 179 if (path == string.Empty)
180 { 180 {
181 foundFolders.Add(startFolder); 181 foundFolders.Add(startFolder);
@@ -189,17 +189,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
189 foundFolders.Add(startFolder); 189 foundFolders.Add(startFolder);
190 return foundFolders; 190 return foundFolders;
191 } 191 }
192 192
193 // If the path isn't just / then trim any starting extraneous slashes 193 // If the path isn't just / then trim any starting extraneous slashes
194 path = path.TrimStart(new char[] { PATH_DELIMITER }); 194 path = path.TrimStart(new char[] { PATH_DELIMITER });
195 195
196// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Adjusted path in FindFolderByPath() is [{0}]", path); 196// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Adjusted path in FindFolderByPath() is [{0}]", path);
197 197
198 string[] components = SplitEscapedPath(path); 198 string[] components = SplitEscapedPath(path);
199 components[0] = UnescapePath(components[0]); 199 components[0] = UnescapePath(components[0]);
200 200
201 //string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None); 201 //string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None);
202 202
203 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 203 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
204 204
205// m_log.DebugFormat( 205// m_log.DebugFormat(
@@ -230,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
230 /// 230 ///
231 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 231 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
232 /// </remarks> 232 /// </remarks>
233 /// 233 ///
234 /// <param name="inventoryService"> 234 /// <param name="inventoryService">
235 /// Inventory service to query 235 /// Inventory service to query
236 /// </param> 236 /// </param>
@@ -301,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
301 /// 301 ///
302 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 302 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
303 /// </remarks> 303 /// </remarks>
304 /// 304 ///
305 /// <param name="inventoryService">Inventory service to query</param> 305 /// <param name="inventoryService">Inventory service to query</param>
306 /// <param name="startFolder">The folder from which the path starts</param> 306 /// <param name="startFolder">The folder from which the path starts</param>
307 /// <param name="path">The path to the required item.</param> 307 /// <param name="path">The path to the required item.</param>
@@ -313,10 +313,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
313 313
314 // If the path isn't just / then trim any starting extraneous slashes 314 // If the path isn't just / then trim any starting extraneous slashes
315 path = path.TrimStart(new char[] { PATH_DELIMITER }); 315 path = path.TrimStart(new char[] { PATH_DELIMITER });
316 316
317 string[] components = SplitEscapedPath(path); 317 string[] components = SplitEscapedPath(path);
318 components[0] = UnescapePath(components[0]); 318 components[0] = UnescapePath(components[0]);
319 319
320 //string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 320 //string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
321 321
322 if (components.Length == 1) 322 if (components.Length == 1)
@@ -324,15 +324,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
324// m_log.DebugFormat( 324// m_log.DebugFormat(
325// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", 325// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}",
326// components[0], startFolder.Name, startFolder.ID); 326// components[0], startFolder.Name, startFolder.ID);
327 327
328 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); 328 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);
329 329
330// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); 330// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count);
331 331
332 foreach (InventoryItemBase item in items) 332 foreach (InventoryItemBase item in items)
333 { 333 {
334// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); 334// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID);
335 335
336 if (item.Name == components[0]) 336 if (item.Name == components[0])
337 foundItems.Add(item); 337 foundItems.Add(item);
338 } 338 }
@@ -342,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
342// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); 342// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]);
343 343
344 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 344 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
345 345
346 foreach (InventoryFolderBase folder in contents.Folders) 346 foreach (InventoryFolderBase folder in contents.Folders)
347 { 347 {
348 if (folder.Name == components[0]) 348 if (folder.Name == components[0])
@@ -365,9 +365,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
365 public static string[] SplitEscapedPath(string path) 365 public static string[] SplitEscapedPath(string path)
366 { 366 {
367// m_log.DebugFormat("SPLITTING PATH {0}", path); 367// m_log.DebugFormat("SPLITTING PATH {0}", path);
368 368
369 bool singleEscapeChar = false; 369 bool singleEscapeChar = false;
370 370
371 for (int i = 0; i < path.Length; i++) 371 for (int i = 0; i < path.Length; i++)
372 { 372 {
373 if (path[i] == ESCAPE_CHARACTER && !singleEscapeChar) 373 if (path[i] == ESCAPE_CHARACTER && !singleEscapeChar)
@@ -395,7 +395,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
395 public static string UnescapePath(string path) 395 public static string UnescapePath(string path)
396 { 396 {
397// m_log.DebugFormat("ESCAPING PATH {0}", path); 397// m_log.DebugFormat("ESCAPING PATH {0}", path);
398 398
399 StringBuilder sb = new StringBuilder(); 399 StringBuilder sb = new StringBuilder();
400 400
401 bool singleEscapeChar = false; 401 bool singleEscapeChar = false;
@@ -418,7 +418,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 } 418 }
419 419
420// m_log.DebugFormat("ESCAPED PATH TO {0}", sb); 420// m_log.DebugFormat("ESCAPED PATH TO {0}", sb);
421 421
422 return sb.ToString(); 422 return sb.ToString();
423 } 423 }
424 424
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index f002ad7..520ea50 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -218,10 +218,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
218 218
219 // Count inventory items (different to asset count) 219 // Count inventory items (different to asset count)
220 CountItems++; 220 CountItems++;
221 221
222 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset 222 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
223 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) 223 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
224 {
225 int curErrorCntr = m_assetGatherer.ErrorCount;
226 int possible = m_assetGatherer.possibleNotAssetCount;
224 m_assetGatherer.AddForInspection(inventoryItem.AssetID); 227 m_assetGatherer.AddForInspection(inventoryItem.AssetID);
228 m_assetGatherer.GatherAll();
229 curErrorCntr = m_assetGatherer.ErrorCount - curErrorCntr;
230 possible = m_assetGatherer.possibleNotAssetCount - possible;
231
232 if(curErrorCntr > 0 || possible > 0)
233 {
234 if(curErrorCntr > 0)
235 {
236 // path is /name__UUID/name__UUID ...
237 m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references to missing or damaged assets, or not a problem.",
238 inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), path, curErrorCntr);
239//// if(possible > 0)
240//// m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item also contains {0} references that may be to missing or damaged assets or not a problem", possible);
241 }
242//// else if(possible > 0)
243//// {
244//// m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references that may be to missing or damaged assets or not a problem", inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, possible);
245//// }
246 }
247 }
225 } 248 }
226 249
227 /// <summary> 250 /// <summary>
@@ -381,6 +404,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
381 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); 404 string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath);
382 Exception e = new InventoryArchiverException(errorMessage); 405 Exception e = new InventoryArchiverException(errorMessage);
383 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0); 406 m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0);
407 if(m_saveStream != null && m_saveStream.CanWrite)
408 m_saveStream.Close();
384 throw e; 409 throw e;
385 } 410 }
386 411
@@ -420,17 +445,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
420 { 445 {
421 m_assetGatherer.GatherAll(); 446 m_assetGatherer.GatherAll();
422 447
448 int errors = m_assetGatherer.FailedUUIDs.Count;
449
423 m_log.DebugFormat( 450 m_log.DebugFormat(
424 "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); 451 "[INVENTORY ARCHIVER]: The items to save reference {0} possible assets", m_assetGatherer.GatheredUuids.Count + errors);
452 if(errors > 0)
453 m_log.DebugFormat("[INVENTORY ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
425 454
426 AssetsRequest ar 455 AssetsRequest ar = new AssetsRequest(
427 = new AssetsRequest(
428 new AssetsArchiver(m_archiveWriter), 456 new AssetsArchiver(m_archiveWriter),
429 m_assetGatherer.GatheredUuids, m_scene.AssetService, 457 m_assetGatherer.GatheredUuids, m_assetGatherer.FailedUUIDs.Count,
458 m_scene.AssetService,
430 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, 459 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
431 options, ReceivedAllAssets); 460 options, ReceivedAllAssets);
432 461 ar.Execute();
433 WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name));
434 } 462 }
435 else 463 else
436 { 464 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 9c005e4..d50ebf5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -50,6 +50,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 /// <value>
54 /// Enable or disable checking whether the iar user is actually logged in
55 /// </value>
56// public bool DisablePresenceChecks { get; set; }
57
53 public event InventoryArchiveSaved OnInventoryArchiveSaved; 58 public event InventoryArchiveSaved OnInventoryArchiveSaved;
54 public event InventoryArchiveLoaded OnInventoryArchiveLoaded; 59 public event InventoryArchiveLoaded OnInventoryArchiveLoaded;
55 60
@@ -89,6 +94,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
89 94
90 public InventoryArchiverModule() {} 95 public InventoryArchiverModule() {}
91 96
97// public InventoryArchiverModule(bool disablePresenceChecks)
98// {
99// DisablePresenceChecks = disablePresenceChecks;
100 // }
101
92 #region ISharedRegionModule 102 #region ISharedRegionModule
93 103
94 public void Initialise(IConfigSource source) 104 public void Initialise(IConfigSource source)
@@ -162,7 +172,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
162 172
163 public string Name { get { return "Inventory Archiver Module"; } } 173 public string Name { get { return "Inventory Archiver Module"; } }
164 174
165 #endregion 175 #endregion
166 176
167 /// <summary> 177 /// <summary>
168 /// Trigger the inventory archive saved event. 178 /// Trigger the inventory archive saved event.
@@ -204,21 +214,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
204 214
205 if (userInfo != null) 215 if (userInfo != null)
206 { 216 {
207 try 217// if (CheckPresence(userInfo.PrincipalID))
208 { 218// {
209 new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream).Execute(options, UserAccountService); 219 try
210 } 220 {
211 catch (EntryPointNotFoundException e) 221 InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream);
212 { 222 iarReq.Execute(options, UserAccountService);
213 m_log.ErrorFormat( 223 }
214 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 224 catch (EntryPointNotFoundException e)
215 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 225 {
216 m_log.Error(e); 226 m_log.ErrorFormat(
217 227 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
218 return false; 228 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
219 } 229 m_log.Error(e);
220 230
221 return true; 231 return false;
232 }
233
234 return true;
235// }
236// else
237// {
238// m_log.ErrorFormat(
239// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
240// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
241// }
222 } 242 }
223 } 243 }
224 244
@@ -238,21 +258,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
238 258
239 if (userInfo != null) 259 if (userInfo != null)
240 { 260 {
241 try 261// if (CheckPresence(userInfo.PrincipalID))
242 { 262// {
243 new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath).Execute(options, UserAccountService); 263 try
244 } 264 {
245 catch (EntryPointNotFoundException e) 265 InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath);
246 { 266 iarReq.Execute(options, UserAccountService);
247 m_log.ErrorFormat( 267 }
248 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 268 catch (EntryPointNotFoundException e)
249 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 269 {
250 m_log.Error(e); 270 m_log.ErrorFormat(
251 271 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
252 return false; 272 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
253 } 273 m_log.Error(e);
254 274
255 return true; 275 return false;
276 }
277
278 return true;
279// }
280// else
281// {
282// m_log.ErrorFormat(
283// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
284// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
285// }
256 } 286 }
257 } 287 }
258 288
@@ -274,26 +304,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
274 304
275 if (userInfo != null) 305 if (userInfo != null)
276 { 306 {
277 InventoryArchiveReadRequest request; 307// if (CheckPresence(userInfo.PrincipalID))
278 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); 308// {
279 309 InventoryArchiveReadRequest request;
280 try 310 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
281 { 311
282 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge); 312 try
283 } 313 {
284 catch (EntryPointNotFoundException e) 314 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge);
285 { 315 }
286 m_log.ErrorFormat( 316 catch (EntryPointNotFoundException e)
287 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 317 {
288 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 318 m_log.ErrorFormat(
289 m_log.Error(e); 319 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
290 320 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
291 return false; 321 m_log.Error(e);
292 } 322
293 323 return false;
294 UpdateClientWithLoadedNodes(userInfo, request.Execute()); 324 }
295 325
296 return true; 326 UpdateClientWithLoadedNodes(userInfo, request.Execute());
327
328 return true;
329// }
330// else
331// {
332// m_log.ErrorFormat(
333// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
334// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
335// }
297 } 336 }
298 else 337 else
299 m_log.ErrorFormat("[INVENTORY ARCHIVER]: User {0} {1} not found", 338 m_log.ErrorFormat("[INVENTORY ARCHIVER]: User {0} {1} not found",
@@ -313,26 +352,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
313 352
314 if (userInfo != null) 353 if (userInfo != null)
315 { 354 {
316 InventoryArchiveReadRequest request; 355// if (CheckPresence(userInfo.PrincipalID))
317 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false); 356// {
318 357 InventoryArchiveReadRequest request;
319 try 358 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
320 { 359
321 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge); 360 try
322 } 361 {
323 catch (EntryPointNotFoundException e) 362 request = new InventoryArchiveReadRequest(id, this, m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge);
324 { 363 }
325 m_log.ErrorFormat( 364 catch (EntryPointNotFoundException e)
326 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." 365 {
327 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 366 m_log.ErrorFormat(
328 m_log.Error(e); 367 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
329 368 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
330 return false; 369 m_log.Error(e);
331 } 370
332 371 return false;
333 UpdateClientWithLoadedNodes(userInfo, request.Execute()); 372 }
334 373
335 return true; 374 UpdateClientWithLoadedNodes(userInfo, request.Execute());
375
376 return true;
377// }
378// else
379// {
380// m_log.ErrorFormat(
381// "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
382// userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
383// }
336 } 384 }
337 } 385 }
338 386
@@ -545,7 +593,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
545 /// Notify the client of loaded nodes if they are logged in 593 /// Notify the client of loaded nodes if they are logged in
546 /// </summary> 594 /// </summary>
547 /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param> 595 /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param>
548 private void UpdateClientWithLoadedNodes(UserAccount userInfo, HashSet<InventoryNodeBase> loadedNodes) 596 private void UpdateClientWithLoadedNodes(UserAccount userInfo, Dictionary<UUID, InventoryNodeBase> loadedNodes)
549 { 597 {
550 if (loadedNodes.Count == 0) 598 if (loadedNodes.Count == 0)
551 return; 599 return;
@@ -556,7 +604,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
556 604
557 if (user != null && !user.IsChildAgent) 605 if (user != null && !user.IsChildAgent)
558 { 606 {
559 foreach (InventoryNodeBase node in loadedNodes) 607 foreach (InventoryNodeBase node in loadedNodes.Values)
560 { 608 {
561// m_log.DebugFormat( 609// m_log.DebugFormat(
562// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}", 610// "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}",
@@ -569,5 +617,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
569 } 617 }
570 } 618 }
571 } 619 }
620
621// /// <summary>
622// /// Check if the given user is present in any of the scenes.
623// /// </summary>
624// /// <param name="userId">The user to check</param>
625// /// <returns>true if the user is in any of the scenes, false otherwise</returns>
626// protected bool CheckPresence(UUID userId)
627// {
628// if (DisablePresenceChecks)
629// return true;
630//
631// foreach (Scene scene in m_scenes.Values)
632// {
633// ScenePresence p;
634// if ((p = scene.GetScenePresence(userId)) != null)
635// {
636// p.ControllingClient.SendAgentAlertMessage("Inventory operation has been started", false);
637// return true;
638// }
639// }
640//
641// return false;
642// }
572 } 643 }
573} 644}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
index c2e645f..86eca17 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
@@ -56,23 +56,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
56 { 56 {
57 TestHelpers.InMethod(); 57 TestHelpers.InMethod();
58// log4net.Config.XmlConfigurator.Configure(); 58// log4net.Config.XmlConfigurator.Configure();
59 59
60 SerialiserModule serialiserModule = new SerialiserModule(); 60 SerialiserModule serialiserModule = new SerialiserModule();
61 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 61 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
62 62
63 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene 63 // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene
64 Scene scene = new SceneHelpers().SetupScene(); 64 Scene scene = new SceneHelpers().SetupScene();
65 65
66 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 66 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
67 67
68 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood"); 68 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood");
69 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); 69 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire");
70 70
71 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 71 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
72 InventoryItemBase foundItem1 72 InventoryItemBase foundItem1
73 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 73 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
74 74
75 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 75 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
76 76
77 // Now try loading to a root child folder 77 // Now try loading to a root child folder
78 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false); 78 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false);
@@ -90,9 +90,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
90 90
91 InventoryItemBase foundItem3 91 InventoryItemBase foundItem3
92 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name); 92 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name);
93 Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); 93 Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3");
94 } 94 }
95 95
96 /// <summary> 96 /// <summary>
97 /// Test that things work when the load path specified starts with a slash 97 /// Test that things work when the load path specified starts with a slash
98 /// </summary> 98 /// </summary>
@@ -101,22 +101,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
101 { 101 {
102 TestHelpers.InMethod(); 102 TestHelpers.InMethod();
103// log4net.Config.XmlConfigurator.Configure(); 103// log4net.Config.XmlConfigurator.Configure();
104 104
105 SerialiserModule serialiserModule = new SerialiserModule(); 105 SerialiserModule serialiserModule = new SerialiserModule();
106 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 106 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
107 Scene scene = new SceneHelpers().SetupScene(); 107 Scene scene = new SceneHelpers().SetupScene();
108 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); 108 SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
109 109
110 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); 110 UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password");
111 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); 111 archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream);
112 112
113 InventoryItemBase foundItem1 113 InventoryItemBase foundItem1
114 = InventoryArchiveUtils.FindItemByPath( 114 = InventoryArchiveUtils.FindItemByPath(
115 scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name); 115 scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name);
116 116
117 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); 117 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()");
118 } 118 }
119 119
120 [Test] 120 [Test]
121 public void TestLoadIarPathWithEscapedChars() 121 public void TestLoadIarPathWithEscapedChars()
122 { 122 {
@@ -137,7 +137,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
137 string userLastName = "Stirrup"; 137 string userLastName = "Stirrup";
138 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); 138 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
139 UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); 139 UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood");
140 140
141 // Create asset 141 // Create asset
142 SceneObjectGroup object1; 142 SceneObjectGroup object1;
143 SceneObjectPart part1; 143 SceneObjectPart part1;
@@ -168,7 +168,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
168 item1.Name = itemName; 168 item1.Name = itemName;
169 item1.AssetID = asset1.FullID; 169 item1.AssetID = asset1.FullID;
170 item1.ID = item1Id; 170 item1.ID = item1Id;
171 InventoryFolderBase objsFolder 171 InventoryFolderBase objsFolder
172 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0]; 172 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0];
173 item1.Folder = objsFolder.ID; 173 item1.Folder = objsFolder.ID;
174 scene.AddInventoryItem(item1); 174 scene.AddInventoryItem(item1);
@@ -189,16 +189,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
189 InventoryItemBase foundItem1 189 InventoryItemBase foundItem1
190 = InventoryArchiveUtils.FindItemByPath( 190 = InventoryArchiveUtils.FindItemByPath(
191 scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); 191 scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName);
192 192
193 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 193 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
194// Assert.That( 194// Assert.That(
195// foundItem1.CreatorId, Is.EqualTo(userUuid), 195// foundItem1.CreatorId, Is.EqualTo(userUuid),
196// "Loaded item non-uuid creator doesn't match that of the loading user"); 196// "Loaded item non-uuid creator doesn't match that of the loading user");
197 Assert.That( 197 Assert.That(
198 foundItem1.Name, Is.EqualTo(itemName), 198 foundItem1.Name, Is.EqualTo(itemName),
199 "Loaded item name doesn't match saved name"); 199 "Loaded item name doesn't match saved name");
200 } 200 }
201 201
202 /// <summary> 202 /// <summary>
203 /// Test replication of an archive path to the user's inventory. 203 /// Test replication of an archive path to the user's inventory.
204 /// </summary> 204 /// </summary>
@@ -207,21 +207,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
207 { 207 {
208 TestHelpers.InMethod(); 208 TestHelpers.InMethod();
209// log4net.Config.XmlConfigurator.Configure(); 209// log4net.Config.XmlConfigurator.Configure();
210 210
211 Scene scene = new SceneHelpers().SetupScene(); 211 Scene scene = new SceneHelpers().SetupScene();
212 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 212 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
213 213
214 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); 214 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
215 HashSet<InventoryNodeBase> nodesLoaded = new HashSet<InventoryNodeBase>(); 215 Dictionary<UUID, InventoryNodeBase> nodesLoaded = new Dictionary<UUID, InventoryNodeBase>();
216 216
217 string folder1Name = "1"; 217 string folder1Name = "1";
218 string folder2aName = "2a"; 218 string folder2aName = "2a";
219 string folder2bName = "2b"; 219 string folder2bName = "2b";
220 220
221 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); 221 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random());
222 string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random()); 222 string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random());
223 string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random()); 223 string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random());
224 224
225 string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName }); 225 string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName });
226 string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName }); 226 string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName });
227 227
@@ -229,42 +229,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
229 // Test replication of path1 229 // Test replication of path1
230 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) 230 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
231 .ReplicateArchivePathToUserInventory( 231 .ReplicateArchivePathToUserInventory(
232 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 232 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
233 foldersCreated, nodesLoaded); 233 foldersCreated, nodesLoaded);
234 234
235 List<InventoryFolderBase> folder1Candidates 235 List<InventoryFolderBase> folder1Candidates
236 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); 236 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name);
237 Assert.That(folder1Candidates.Count, Is.EqualTo(1)); 237 Assert.That(folder1Candidates.Count, Is.EqualTo(1));
238 238
239 InventoryFolderBase folder1 = folder1Candidates[0]; 239 InventoryFolderBase folder1 = folder1Candidates[0];
240 List<InventoryFolderBase> folder2aCandidates 240 List<InventoryFolderBase> folder2aCandidates
241 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); 241 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName);
242 Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); 242 Assert.That(folder2aCandidates.Count, Is.EqualTo(1));
243 } 243 }
244 244
245 { 245 {
246 // Test replication of path2 246 // Test replication of path2
247 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) 247 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
248 .ReplicateArchivePathToUserInventory( 248 .ReplicateArchivePathToUserInventory(
249 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 249 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
250 foldersCreated, nodesLoaded); 250 foldersCreated, nodesLoaded);
251 251
252 List<InventoryFolderBase> folder1Candidates 252 List<InventoryFolderBase> folder1Candidates
253 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); 253 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name);
254 Assert.That(folder1Candidates.Count, Is.EqualTo(1)); 254 Assert.That(folder1Candidates.Count, Is.EqualTo(1));
255 255
256 InventoryFolderBase folder1 = folder1Candidates[0]; 256 InventoryFolderBase folder1 = folder1Candidates[0];
257 257
258 List<InventoryFolderBase> folder2aCandidates 258 List<InventoryFolderBase> folder2aCandidates
259 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); 259 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName);
260 Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); 260 Assert.That(folder2aCandidates.Count, Is.EqualTo(1));
261 261
262 List<InventoryFolderBase> folder2bCandidates 262 List<InventoryFolderBase> folder2bCandidates
263 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName); 263 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName);
264 Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); 264 Assert.That(folder2bCandidates.Count, Is.EqualTo(1));
265 } 265 }
266 } 266 }
267 267
268 /// <summary> 268 /// <summary>
269 /// Test replication of a partly existing archive path to the user's inventory. This should create 269 /// Test replication of a partly existing archive path to the user's inventory. This should create
270 /// a duplicate path without the merge option. 270 /// a duplicate path without the merge option.
@@ -274,31 +274,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
274 { 274 {
275 TestHelpers.InMethod(); 275 TestHelpers.InMethod();
276 //log4net.Config.XmlConfigurator.Configure(); 276 //log4net.Config.XmlConfigurator.Configure();
277 277
278 Scene scene = new SceneHelpers().SetupScene(); 278 Scene scene = new SceneHelpers().SetupScene();
279 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 279 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
280 280
281 string folder1ExistingName = "a"; 281 string folder1ExistingName = "a";
282 string folder2Name = "b"; 282 string folder2Name = "b";
283 283
284 InventoryFolderBase folder1 284 InventoryFolderBase folder1
285 = UserInventoryHelpers.CreateInventoryFolder( 285 = UserInventoryHelpers.CreateInventoryFolder(
286 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); 286 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false);
287 287
288 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); 288 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
289 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 289 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
290 290
291 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 291 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
292 292
293 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) 293 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
294 .ReplicateArchivePathToUserInventory( 294 .ReplicateArchivePathToUserInventory(
295 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 295 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
296 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 296 new Dictionary<string, InventoryFolderBase>(), new Dictionary<UUID, InventoryNodeBase>());
297 297
298 List<InventoryFolderBase> folder1PostCandidates 298 List<InventoryFolderBase> folder1PostCandidates
299 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 299 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
300 Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); 300 Assert.That(folder1PostCandidates.Count, Is.EqualTo(2));
301 301
302 // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. 302 // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder.
303 InventoryFolderBase folder1Post = null; 303 InventoryFolderBase folder1Post = null;
304 foreach (InventoryFolderBase folder in folder1PostCandidates) 304 foreach (InventoryFolderBase folder in folder1PostCandidates)
@@ -311,11 +311,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
311 } 311 }
312// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); 312// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID));
313 313
314 List<InventoryFolderBase> folder2PostCandidates 314 List<InventoryFolderBase> folder2PostCandidates
315 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b"); 315 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b");
316 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); 316 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
317 } 317 }
318 318
319 /// <summary> 319 /// <summary>
320 /// Test replication of a partly existing archive path to the user's inventory. This should create 320 /// Test replication of a partly existing archive path to the user's inventory. This should create
321 /// a merged path. 321 /// a merged path.
@@ -325,33 +325,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
325 { 325 {
326 TestHelpers.InMethod(); 326 TestHelpers.InMethod();
327// log4net.Config.XmlConfigurator.Configure(); 327// log4net.Config.XmlConfigurator.Configure();
328 328
329 Scene scene = new SceneHelpers().SetupScene(); 329 Scene scene = new SceneHelpers().SetupScene();
330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); 330 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene);
331 331
332 string folder1ExistingName = "a"; 332 string folder1ExistingName = "a";
333 string folder2Name = "b"; 333 string folder2Name = "b";
334 334
335 InventoryFolderBase folder1 335 InventoryFolderBase folder1
336 = UserInventoryHelpers.CreateInventoryFolder( 336 = UserInventoryHelpers.CreateInventoryFolder(
337 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); 337 scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false);
338 338
339 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); 339 string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
340 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 340 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
341 341
342 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 342 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
343 343
344 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true) 344 new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true)
345 .ReplicateArchivePathToUserInventory( 345 .ReplicateArchivePathToUserInventory(
346 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 346 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
347 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 347 new Dictionary<string, InventoryFolderBase>(), new Dictionary<UUID, InventoryNodeBase>());
348 348
349 List<InventoryFolderBase> folder1PostCandidates 349 List<InventoryFolderBase> folder1PostCandidates
350 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); 350 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
351 Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); 351 Assert.That(folder1PostCandidates.Count, Is.EqualTo(1));
352 Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); 352 Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID));
353 353
354 List<InventoryFolderBase> folder2PostCandidates 354 List<InventoryFolderBase> folder2PostCandidates
355 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b"); 355 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b");
356 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); 356 Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
357 } 357 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
index 57b4f80..d0bdc91 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
47{ 47{
48 [TestFixture] 48 [TestFixture]
49 public class InventoryArchiveLoadTests : InventoryArchiveTestCase 49 public class InventoryArchiveLoadTests : InventoryArchiveTestCase
50 { 50 {
51 protected TestScene m_scene; 51 protected TestScene m_scene;
52 protected InventoryArchiverModule m_archiverModule; 52 protected InventoryArchiverModule m_archiverModule;
53 53
@@ -55,12 +55,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
55 public override void SetUp() 55 public override void SetUp()
56 { 56 {
57 base.SetUp(); 57 base.SetUp();
58 58
59 SerialiserModule serialiserModule = new SerialiserModule(); 59 SerialiserModule serialiserModule = new SerialiserModule();
60 m_archiverModule = new InventoryArchiverModule(); 60 m_archiverModule = new InventoryArchiverModule();
61 61
62 m_scene = new SceneHelpers().SetupScene(); 62 m_scene = new SceneHelpers().SetupScene();
63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); 63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
64 } 64 }
65 65
66 [Test] 66 [Test]
@@ -68,35 +68,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
68 { 68 {
69 TestHelpers.InMethod(); 69 TestHelpers.InMethod();
70// TestHelpers.EnableLogging(); 70// TestHelpers.EnableLogging();
71 71
72 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); 72 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password");
73 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); 73 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
74 74
75 InventoryItemBase coaItem 75 InventoryItemBase coaItem
76 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); 76 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName);
77 77
78 Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); 78 Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1");
79 79
80 string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); 80 string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID);
81 81
82 CoalescedSceneObjects coa; 82 CoalescedSceneObjects coa;
83 bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); 83 bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa);
84 84
85 Assert.That(readResult, Is.True); 85 Assert.That(readResult, Is.True);
86 Assert.That(coa.Count, Is.EqualTo(2)); 86 Assert.That(coa.Count, Is.EqualTo(2));
87 87
88 List<SceneObjectGroup> coaObjects = coa.Objects; 88 List<SceneObjectGroup> coaObjects = coa.Objects;
89 Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); 89 Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120")));
90 Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); 90 Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45)));
91 91
92 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); 92 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140")));
93 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); 93 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75)));
94 } 94 }
95 95
96 /// <summary> 96 /// <summary>
97 /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized 97 /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized
98 /// objects. 98 /// objects.
99 /// </summary> 99 /// </summary>
100 [Test] 100 [Test]
101 public void TestLoadIarCreatorAccountPresent() 101 public void TestLoadIarCreatorAccountPresent()
102 { 102 {
@@ -105,26 +105,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
105 105
106 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); 106 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood");
107 107
108 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); 108 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream);
109 InventoryItemBase foundItem1 109 InventoryItemBase foundItem1
110 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name); 110 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name);
111 111
112 Assert.That( 112 Assert.That(
113 foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()), 113 foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()),
114 "Loaded item non-uuid creator doesn't match original"); 114 "Loaded item non-uuid creator doesn't match original");
115 Assert.That( 115 Assert.That(
116 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID), 116 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID),
117 "Loaded item uuid creator doesn't match original"); 117 "Loaded item uuid creator doesn't match original");
118 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID), 118 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID),
119 "Loaded item owner doesn't match inventory reciever"); 119 "Loaded item owner doesn't match inventory reciever");
120 120
121 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 121 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
122 string xmlData = Utils.BytesToString(asset1.Data); 122 string xmlData = Utils.BytesToString(asset1.Data);
123 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 123 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
124 124
125 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); 125 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
126 } 126 }
127 127
128// /// <summary> 128// /// <summary>
129// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 129// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
130// /// an account exists with the same name as the creator, though not the same id. 130// /// an account exists with the same name as the creator, though not the same id.
@@ -137,24 +137,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
137// 137//
138// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); 138// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
139// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); 139// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
140// 140//
141// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 141// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
142// InventoryItemBase foundItem1 142// InventoryItemBase foundItem1
143// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 143// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
144// 144//
145// Assert.That( 145// Assert.That(
146// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), 146// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
147// "Loaded item non-uuid creator doesn't match original"); 147// "Loaded item non-uuid creator doesn't match original");
148// Assert.That( 148// Assert.That(
149// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), 149// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
150// "Loaded item uuid creator doesn't match original"); 150// "Loaded item uuid creator doesn't match original");
151// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), 151// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
152// "Loaded item owner doesn't match inventory reciever"); 152// "Loaded item owner doesn't match inventory reciever");
153// 153//
154// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 154// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
155// string xmlData = Utils.BytesToString(asset1.Data); 155// string xmlData = Utils.BytesToString(asset1.Data);
156// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 156// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
157// 157//
158// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); 158// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
159// } 159// }
160 160
@@ -167,26 +167,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
167 { 167 {
168 TestHelpers.InMethod(); 168 TestHelpers.InMethod();
169// log4net.Config.XmlConfigurator.Configure(); 169// log4net.Config.XmlConfigurator.Configure();
170 170
171 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); 171 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password");
172 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); 172 m_archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream);
173 173
174 InventoryItemBase foundItem1 174 InventoryItemBase foundItem1
175 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 175 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
176 176
177 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); 177 Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1");
178 Assert.That( 178 Assert.That(
179 foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()), 179 foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()),
180 "Loaded item non-uuid creator doesn't match that of the loading user"); 180 "Loaded item non-uuid creator doesn't match that of the loading user");
181 Assert.That( 181 Assert.That(
182 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID), 182 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID),
183 "Loaded item uuid creator doesn't match that of the loading user"); 183 "Loaded item uuid creator doesn't match that of the loading user");
184 184
185 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 185 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
186 string xmlData = Utils.BytesToString(asset1.Data); 186 string xmlData = Utils.BytesToString(asset1.Data);
187 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 187 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
188 188
189 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); 189 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID));
190 } 190 }
191 } 191 }
192} \ No newline at end of file 192} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
index 7265405..bd112b4 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
@@ -50,19 +50,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
50 { 50 {
51 protected TestScene m_scene; 51 protected TestScene m_scene;
52 protected InventoryArchiverModule m_archiverModule; 52 protected InventoryArchiverModule m_archiverModule;
53 53
54 [SetUp] 54 [SetUp]
55 public override void SetUp() 55 public override void SetUp()
56 { 56 {
57 base.SetUp(); 57 base.SetUp();
58 58
59 SerialiserModule serialiserModule = new SerialiserModule(); 59 SerialiserModule serialiserModule = new SerialiserModule();
60 m_archiverModule = new InventoryArchiverModule(); 60 m_archiverModule = new InventoryArchiverModule();
61 61
62 m_scene = new SceneHelpers().SetupScene(); 62 m_scene = new SceneHelpers().SetupScene();
63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); 63 SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule);
64 } 64 }
65 65
66 /// <summary> 66 /// <summary>
67 /// Test that the IAR has the required files in the right order. 67 /// Test that the IAR has the required files in the right order.
68 /// </summary> 68 /// </summary>
@@ -73,20 +73,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
73 public void TestOrder() 73 public void TestOrder()
74 { 74 {
75 TestHelpers.InMethod(); 75 TestHelpers.InMethod();
76// log4net.Config.XmlConfigurator.Configure(); 76// log4net.Config.XmlConfigurator.Configure();
77 77
78 MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes); 78 MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes);
79 TarArchiveReader tar = new TarArchiveReader(archiveReadStream); 79 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
80 string filePath; 80 string filePath;
81 TarArchiveReader.TarEntryType tarEntryType; 81 TarArchiveReader.TarEntryType tarEntryType;
82 82
83 byte[] data = tar.ReadEntry(out filePath, out tarEntryType); 83 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
84 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 84 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
85 85
86 InventoryArchiveReadRequest iarr 86 InventoryArchiveReadRequest iarr
87 = new InventoryArchiveReadRequest(UUID.Random(), null, null, null, null, null, null, (Stream)null, false); 87 = new InventoryArchiveReadRequest(UUID.Random(), null, null, null, null, null, null, (Stream)null, false);
88 iarr.LoadControlFile(filePath, data); 88 iarr.LoadControlFile(filePath, data);
89 89
90 Assert.That(iarr.ControlFileLoaded, Is.True); 90 Assert.That(iarr.ControlFileLoaded, Is.True);
91 } 91 }
92 92
@@ -119,22 +119,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
119// InventoryArchiveUtils. 119// InventoryArchiveUtils.
120 bool gotObjectsFolder = false; 120 bool gotObjectsFolder = false;
121 121
122 string objectsFolderName 122 string objectsFolderName
123 = string.Format( 123 = string.Format(
124 "{0}{1}", 124 "{0}{1}",
125 ArchiveConstants.INVENTORY_PATH, 125 ArchiveConstants.INVENTORY_PATH,
126 InventoryArchiveWriteRequest.CreateArchiveFolderName( 126 InventoryArchiveWriteRequest.CreateArchiveFolderName(
127 UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects"))); 127 UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects")));
128 128
129 string filePath; 129 string filePath;
130 TarArchiveReader.TarEntryType tarEntryType; 130 TarArchiveReader.TarEntryType tarEntryType;
131 131
132 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 132 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
133 { 133 {
134// Console.WriteLine("Got {0}", filePath); 134// Console.WriteLine("Got {0}", filePath);
135 135
136 // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory() 136 // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory()
137 // XXX: But really we need to stop all that stuff being created in tests or check for such folders 137 // XXX: But really we need to stop all that stuff being created in tests or check for such folders
138 // more thoroughly 138 // more thoroughly
139 if (filePath == objectsFolderName) 139 if (filePath == objectsFolderName)
140 gotObjectsFolder = true; 140 gotObjectsFolder = true;
@@ -157,19 +157,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
157 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); 157 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword);
158 158
159 // Create base folder 159 // Create base folder
160 InventoryFolderBase f1 160 InventoryFolderBase f1
161 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true); 161 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true);
162 162
163 // Create item1 163 // Create item1
164 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5); 164 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5);
165 InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1"); 165 InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1");
166 166
167 // Create embedded folder 167 // Create embedded folder
168 InventoryFolderBase f1_1 168 InventoryFolderBase f1_1
169 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true); 169 = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true);
170 170
171 // Create embedded item 171 // Create embedded item
172 SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6); 172 SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6);
173 InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1"); 173 InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1");
174 174
175 MemoryStream archiveWriteStream = new MemoryStream(); 175 MemoryStream archiveWriteStream = new MemoryStream();
@@ -188,18 +188,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
188// InventoryArchiveUtils. 188// InventoryArchiveUtils.
189 bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false; 189 bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false;
190 190
191 string f1FileName 191 string f1FileName
192 = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1)); 192 = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1));
193 string f1_1FileName 193 string f1_1FileName
194 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1)); 194 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1));
195 string so1FileName 195 string so1FileName
196 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1)); 196 = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1));
197 string so2FileName 197 string so2FileName
198 = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2)); 198 = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2));
199 199
200 string filePath; 200 string filePath;
201 TarArchiveReader.TarEntryType tarEntryType; 201 TarArchiveReader.TarEntryType tarEntryType;
202 202
203 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 203 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
204 { 204 {
205// Console.WriteLine("Got {0}", filePath); 205// Console.WriteLine("Got {0}", filePath);
@@ -222,7 +222,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
222 222
223 // TODO: Test presence of more files and contents of files. 223 // TODO: Test presence of more files and contents of files.
224 } 224 }
225 225
226 /// <summary> 226 /// <summary>
227 /// Test saving a single inventory item to an IAR 227 /// Test saving a single inventory item to an IAR
228 /// (subject to change since there is no fixed format yet). 228 /// (subject to change since there is no fixed format yet).
@@ -239,10 +239,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
239 string userPassword = "troll"; 239 string userPassword = "troll";
240 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); 240 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
241 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); 241 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword);
242 242
243 // Create asset 243 // Create asset
244 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); 244 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
245 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); 245 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50);
246 246
247 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 247 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
248 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); 248 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
@@ -255,7 +255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
255 item1.Name = item1Name; 255 item1.Name = item1Name;
256 item1.AssetID = asset1.FullID; 256 item1.AssetID = asset1.FullID;
257 item1.ID = item1Id; 257 item1.ID = item1Id;
258 InventoryFolderBase objsFolder 258 InventoryFolderBase objsFolder
259 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; 259 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0];
260 item1.Folder = objsFolder.ID; 260 item1.Folder = objsFolder.ID;
261 m_scene.AddInventoryItem(item1); 261 m_scene.AddInventoryItem(item1);
@@ -285,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
285 TarArchiveReader.TarEntryType tarEntryType; 285 TarArchiveReader.TarEntryType tarEntryType;
286 286
287// Console.WriteLine("Reading archive"); 287// Console.WriteLine("Reading archive");
288 288
289 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 289 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
290 { 290 {
291 Console.WriteLine("Got {0}", filePath); 291 Console.WriteLine("Got {0}", filePath);
@@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
294// { 294// {
295// gotControlFile = true; 295// gotControlFile = true;
296// } 296// }
297 297
298 if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) 298 if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml"))
299 { 299 {
300// string fileName = filePath.Remove(0, "Objects/".Length); 300// string fileName = filePath.Remove(0, "Objects/".Length);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index 519c697..0b65829 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -49,35 +49,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49 public class InventoryArchiveTestCase : OpenSimTestCase 49 public class InventoryArchiveTestCase : OpenSimTestCase
50 { 50 {
51 protected ManualResetEvent mre = new ManualResetEvent(false); 51 protected ManualResetEvent mre = new ManualResetEvent(false);
52 52
53 /// <summary> 53 /// <summary>
54 /// A raw array of bytes that we'll use to create an IAR memory stream suitable for isolated use in each test. 54 /// A raw array of bytes that we'll use to create an IAR memory stream suitable for isolated use in each test.
55 /// </summary> 55 /// </summary>
56 protected byte[] m_iarStreamBytes; 56 protected byte[] m_iarStreamBytes;
57 57
58 /// <summary> 58 /// <summary>
59 /// Stream of data representing a common IAR for load tests. 59 /// Stream of data representing a common IAR for load tests.
60 /// </summary> 60 /// </summary>
61 protected MemoryStream m_iarStream; 61 protected MemoryStream m_iarStream;
62 62
63 protected UserAccount m_uaMT 63 protected UserAccount m_uaMT
64 = new UserAccount { 64 = new UserAccount {
65 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), 65 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"),
66 FirstName = "Mr", 66 FirstName = "Mr",
67 LastName = "Tiddles" }; 67 LastName = "Tiddles" };
68 68
69 protected UserAccount m_uaLL1 69 protected UserAccount m_uaLL1
70 = new UserAccount { 70 = new UserAccount {
71 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), 71 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"),
72 FirstName = "Lord", 72 FirstName = "Lord",
73 LastName = "Lucan" }; 73 LastName = "Lucan" };
74 74
75 protected UserAccount m_uaLL2 75 protected UserAccount m_uaLL2
76 = new UserAccount { 76 = new UserAccount {
77 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"), 77 PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"),
78 FirstName = "Lord", 78 FirstName = "Lord",
79 LastName = "Lucan" }; 79 LastName = "Lucan" };
80 80
81 protected string m_item1Name = "Ray Gun Item"; 81 protected string m_item1Name = "Ray Gun Item";
82 protected string m_coaItemName = "Coalesced Item"; 82 protected string m_coaItemName = "Coalesced Item";
83 83
@@ -105,72 +105,72 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
105 base.SetUp(); 105 base.SetUp();
106 m_iarStream = new MemoryStream(m_iarStreamBytes); 106 m_iarStream = new MemoryStream(m_iarStreamBytes);
107 } 107 }
108 108
109 protected void ConstructDefaultIarBytesForTestLoad() 109 protected void ConstructDefaultIarBytesForTestLoad()
110 { 110 {
111// log4net.Config.XmlConfigurator.Configure(); 111// log4net.Config.XmlConfigurator.Configure();
112 112
113 InventoryArchiverModule archiverModule = new InventoryArchiverModule(); 113 InventoryArchiverModule archiverModule = new InventoryArchiverModule();
114 Scene scene = new SceneHelpers().SetupScene(); 114 Scene scene = new SceneHelpers().SetupScene();
115 SceneHelpers.SetupSceneModules(scene, archiverModule); 115 SceneHelpers.SetupSceneModules(scene, archiverModule);
116 116
117 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); 117 UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire");
118 118
119 MemoryStream archiveWriteStream = new MemoryStream(); 119 MemoryStream archiveWriteStream = new MemoryStream();
120 120
121 // Create scene object asset 121 // Create scene object asset
122 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); 122 UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040");
123 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50); 123 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50);
124 124
125 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 125 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
126 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); 126 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
127 scene.AssetService.Store(asset1); 127 scene.AssetService.Store(asset1);
128 128
129 // Create scene object item 129 // Create scene object item
130 InventoryItemBase item1 = new InventoryItemBase(); 130 InventoryItemBase item1 = new InventoryItemBase();
131 item1.Name = m_item1Name; 131 item1.Name = m_item1Name;
132 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020"); 132 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020");
133 item1.AssetID = asset1.FullID; 133 item1.AssetID = asset1.FullID;
134 item1.GroupID = UUID.Random(); 134 item1.GroupID = UUID.Random();
135 item1.CreatorId = m_uaLL1.PrincipalID.ToString(); 135 item1.CreatorId = m_uaLL1.PrincipalID.ToString();
136 item1.Owner = m_uaLL1.PrincipalID; 136 item1.Owner = m_uaLL1.PrincipalID;
137 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; 137 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
138 scene.AddInventoryItem(item1); 138 scene.AddInventoryItem(item1);
139 139
140 // Create coalesced objects asset 140 // Create coalesced objects asset
141 SceneObjectGroup cobj1 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object1", 0x120); 141 SceneObjectGroup cobj1 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object1", 0x120);
142 cobj1.AbsolutePosition = new Vector3(15, 30, 45); 142 cobj1.AbsolutePosition = new Vector3(15, 30, 45);
143 143
144 SceneObjectGroup cobj2 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object2", 0x140); 144 SceneObjectGroup cobj2 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object2", 0x140);
145 cobj2.AbsolutePosition = new Vector3(25, 50, 75); 145 cobj2.AbsolutePosition = new Vector3(25, 50, 75);
146 146
147 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_uaLL1.PrincipalID, cobj1, cobj2); 147 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_uaLL1.PrincipalID, cobj1, cobj2);
148 148
149 AssetBase coaAsset = AssetHelpers.CreateAsset(0x160, coa); 149 AssetBase coaAsset = AssetHelpers.CreateAsset(0x160, coa);
150 scene.AssetService.Store(coaAsset); 150 scene.AssetService.Store(coaAsset);
151 151
152 // Create coalesced objects inventory item 152 // Create coalesced objects inventory item
153 InventoryItemBase coaItem = new InventoryItemBase(); 153 InventoryItemBase coaItem = new InventoryItemBase();
154 coaItem.Name = m_coaItemName; 154 coaItem.Name = m_coaItemName;
155 coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180"); 155 coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180");
156 coaItem.AssetID = coaAsset.FullID; 156 coaItem.AssetID = coaAsset.FullID;
157 coaItem.GroupID = UUID.Random(); 157 coaItem.GroupID = UUID.Random();
158 coaItem.CreatorId = m_uaLL1.PrincipalID.ToString(); 158 coaItem.CreatorId = m_uaLL1.PrincipalID.ToString();
159 coaItem.Owner = m_uaLL1.PrincipalID; 159 coaItem.Owner = m_uaLL1.PrincipalID;
160 coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; 160 coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
161 scene.AddInventoryItem(coaItem); 161 scene.AddInventoryItem(coaItem);
162 162
163 archiverModule.ArchiveInventory( 163 archiverModule.ArchiveInventory(
164 UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream); 164 UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream);
165 165
166 m_iarStreamBytes = archiveWriteStream.ToArray(); 166 m_iarStreamBytes = archiveWriteStream.ToArray();
167 } 167 }
168 168
169 protected void SaveCompleted( 169 protected void SaveCompleted(
170 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, 170 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
171 Exception reportedException, int SaveCount, int FilterCount) 171 Exception reportedException, int SaveCount, int FilterCount)
172 { 172 {
173 mre.Set(); 173 mre.Set();
174 } 174 }
175 } 175 }
176} \ No newline at end of file 176} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index bba48cc..5d7f25c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -149,10 +149,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
150 { 150 {
151// m_log.DebugFormat( 151// m_log.DebugFormat(
152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}", 152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}",
153// (InstantMessageDialog)im.dialog, client.Name, 153// (InstantMessageDialog)im.dialog, client.Name,
154// im.fromAgentID, im.fromAgentName, im.toAgentID); 154// im.fromAgentID, im.fromAgentName, im.toAgentID);
155 155
156 Scene scene = FindClientScene(client.AgentId); 156 Scene scene = FindClientScene(client.AgentId);
157 157
158 if (scene == null) // Something seriously wrong here. 158 if (scene == null) // Something seriously wrong here.
@@ -164,31 +164,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
164 164
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
173 AssetType assetType = (AssetType)im.binaryBucket[0]; 173 AssetType assetType = (AssetType)im.binaryBucket[0];
174 174
175 if (AssetType.Folder == assetType) 175 if (AssetType.Folder == assetType)
176 { 176 {
177 UUID folderID = new UUID(im.binaryBucket, 1); 177 UUID folderID = new UUID(im.binaryBucket, 1);
178 178
179 m_log.DebugFormat( 179 m_log.DebugFormat(
180 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", 180 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory",
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 {
188 client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); 188 client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false);
189 return; 189 return;
190 } 190 }
191 191
192 // The outgoing binary bucket should contain only the byte which signals an asset folder is 192 // The outgoing binary bucket should contain only the byte which signals an asset folder is
193 // being copied and the following bytes for the copied folder's UUID 193 // being copied and the following bytes for the copied folder's UUID
194 copyID = folderCopy.ID; 194 copyID = folderCopy.ID;
@@ -196,7 +196,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
196 im.binaryBucket = new byte[1 + copyIDBytes.Length]; 196 im.binaryBucket = new byte[1 + copyIDBytes.Length];
197 im.binaryBucket[0] = (byte)AssetType.Folder; 197 im.binaryBucket[0] = (byte)AssetType.Folder;
198 Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length); 198 Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length);
199 199
200 if (user != null) 200 if (user != null)
201 user.ControllingClient.SendBulkUpdateInventory(folderCopy); 201 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
202 202
@@ -225,10 +225,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
225 client.SendAgentAlertMessage(message, false); 225 client.SendAgentAlertMessage(message, false);
226 return; 226 return;
227 } 227 }
228 228
229 copyID = itemCopy.ID; 229 copyID = itemCopy.ID;
230 Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16); 230 Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16);
231 231
232 if (user != null) 232 if (user != null)
233 user.ControllingClient.SendBulkUpdateInventory(itemCopy); 233 user.ControllingClient.SendBulkUpdateInventory(itemCopy);
234 234
@@ -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.
@@ -251,15 +253,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
251 else 253 else
252 { 254 {
253 if (m_TransferModule != null) 255 if (m_TransferModule != null)
254 m_TransferModule.SendInstantMessage(im, delegate(bool success) 256 m_TransferModule.SendInstantMessage(im, delegate(bool success)
255 { 257 {
256 if (!success) 258 if (!success)
257 client.SendAlertMessage("User not online. Inventory has been saved"); 259 client.SendAlertMessage("User not online. Inventory has been saved");
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 = invService.GetFolder(client.AgentId, inventoryID);
274
275 if (folder != null)
276 {
277 if (im.binaryBucket.Length >= 16)
278 {
279 UUID destFolderID = new UUID(im.binaryBucket, 0);
280 if (destFolderID != UUID.Zero)
281 {
282 InventoryFolderBase destFolder = invService.GetFolder(client.AgentId, destFolderID);
283 if (destFolder != null)
284 {
285 if (folder.ParentID != destFolder.ID)
286 {
287 folder.ParentID = destFolder.ID;
288 invService.MoveFolder(folder);
289 client.SendBulkUpdateInventory(folder);
290 }
291 }
292 }
293 }
294 }
295 }
296
263 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 297 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
264 298
265 if (user != null) // Local 299 if (user != null) // Local
@@ -269,33 +303,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
269 else 303 else
270 { 304 {
271 if (m_TransferModule != null) 305 if (m_TransferModule != null)
272 m_TransferModule.SendInstantMessage(im, delegate(bool success) { 306 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 } 307 }
294 } 308 }
295 309
296 // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name> 310 // XXX: This code was placed here to try and accomodate RLV which moves given folders named #RLV/~<name>
297 // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be 311 // to the requested folder, which in this case is #RLV. However, it is the viewer that appears to be
298 // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet 312 // response from renaming the #RLV/~example folder to ~example. For some reason this is not yet
299 // happening, possibly because we are not sending the correct inventory update messages with the correct 313 // happening, possibly because we are not sending the correct inventory update messages with the correct
300 // transaction IDs 314 // transaction IDs
301 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) 315 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
@@ -310,21 +324,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
310 if (destinationFolderID != UUID.Zero) 324 if (destinationFolderID != UUID.Zero)
311 { 325 {
312 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); 326 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
313 if (destinationFolder == null)
314 {
315 m_log.WarnFormat(
316 "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
317 client.Name, scene.Name, destinationFolderID);
318
319 return;
320 }
321
322 IInventoryService invService = scene.InventoryService; 327 IInventoryService invService = scene.InventoryService;
323 328
324 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 329 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
325 330
326 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 331 InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID);
327 item = invService.GetItem(item);
328 InventoryFolderBase folder = null; 332 InventoryFolderBase folder = null;
329 UUID? previousParentFolderID = null; 333 UUID? previousParentFolderID = null;
330 334
@@ -338,8 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
338 } 342 }
339 else 343 else
340 { 344 {
341 folder = new InventoryFolderBase(inventoryID, client.AgentId); 345 folder = invService.GetFolder(client.AgentId, inventoryID);
342 folder = invService.GetFolder(folder);
343 346
344 if (folder != null) // It's a folder 347 if (folder != null) // It's a folder
345 { 348 {
@@ -352,9 +355,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
352 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). 355 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
353 if (previousParentFolderID != null) 356 if (previousParentFolderID != null)
354 { 357 {
355 InventoryFolderBase previousParentFolder 358 InventoryFolderBase previousParentFolder = invService.GetFolder(client.AgentId, (UUID)previousParentFolderID);
356 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
357 previousParentFolder = invService.GetFolder(previousParentFolder);
358 scene.SendInventoryUpdate(client, previousParentFolder, true, true); 359 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
359 360
360 scene.SendInventoryUpdate(client, destinationFolder, true, true); 361 scene.SendInventoryUpdate(client, destinationFolder, true, true);
@@ -376,11 +377,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
376 377
377 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 378 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
378 379
379 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 380 InventoryItemBase item = invService.GetItem(client.AgentId, inventoryID);
380 item = invService.GetItem(item);
381 InventoryFolderBase folder = null; 381 InventoryFolderBase folder = null;
382 UUID? previousParentFolderID = null; 382 UUID? previousParentFolderID = null;
383 383
384 if (item != null && trashFolder != null) 384 if (item != null && trashFolder != null)
385 { 385 {
386 previousParentFolderID = item.Folder; 386 previousParentFolderID = item.Folder;
@@ -394,37 +394,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
394 } 394 }
395 else 395 else
396 { 396 {
397 folder = new InventoryFolderBase(inventoryID, client.AgentId); 397 folder = invService.GetFolder(client.AgentId, inventoryID);
398 folder = invService.GetFolder(folder);
399 398
400 if (folder != null & trashFolder != null) 399 if (folder != null & trashFolder != null)
401 { 400 {
402 previousParentFolderID = folder.ParentID; 401 previousParentFolderID = folder.ParentID;
403 folder.ParentID = trashFolder.ID; 402 folder.ParentID = trashFolder.ID;
404 invService.MoveFolder(folder); 403 invService.MoveFolder(folder);
404 client.SendBulkUpdateInventory(folder);
405 } 405 }
406 } 406 }
407 407
408 if ((null == item && null == folder) | null == trashFolder) 408 if ((null == item && null == folder) | null == trashFolder)
409 { 409 {
410 string reason = String.Empty; 410 string reason = String.Empty;
411 411
412 if (trashFolder == null) 412 if (trashFolder == null)
413 reason += " Trash folder not found."; 413 reason += " Trash folder not found.";
414 if (item == null) 414 if (item == null)
415 reason += " Item not found."; 415 reason += " Item not found.";
416 if (folder == null) 416 if (folder == null)
417 reason += " Folder not found."; 417 reason += " Folder not found.";
418 418
419 client.SendAgentAlertMessage("Unable to delete "+ 419 client.SendAgentAlertMessage("Unable to delete "+
420 "received inventory" + reason, false); 420 "received inventory" + reason, false);
421 } 421 }
422 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). 422 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
423 else if (previousParentFolderID != null) 423 else if (previousParentFolderID != null)
424 { 424 {
425 InventoryFolderBase previousParentFolder 425 InventoryFolderBase previousParentFolder = invService.GetFolder(client.AgentId, (UUID)previousParentFolderID);
426 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
427 previousParentFolder = invService.GetFolder(previousParentFolder);
428 scene.SendInventoryUpdate(client, previousParentFolder, true, true); 426 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
429 427
430 scene.SendInventoryUpdate(client, trashFolder, true, true); 428 scene.SendInventoryUpdate(client, trashFolder, true, true);
@@ -453,18 +451,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
453 /// <param name="im"></param> 451 /// <param name="im"></param>
454 private void OnGridInstantMessage(GridInstantMessage im) 452 private void OnGridInstantMessage(GridInstantMessage im)
455 { 453 {
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 454 // Check if this is ours to handle
469 // 455 //
470 Scene scene = FindClientScene(new UUID(im.toAgentID)); 456 Scene scene = FindClientScene(new UUID(im.toAgentID));
@@ -475,32 +461,92 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
475 // Find agent to deliver to 461 // Find agent to deliver to
476 // 462 //
477 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 463 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
464 if (user == null)
465 return;
478 466
479 if (user != null) 467 // This requires a little bit of processing because we have to make the
468 // new item visible in the recipient's inventory here
469 //
470 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
480 { 471 {
481 user.ControllingClient.SendInstantMessage(im); 472 if (im.binaryBucket.Length < 17) // Invalid
473 return;
482 474
483 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 475 UUID recipientID = new UUID(im.toAgentID);
476
477 // First byte is the asset type
478 AssetType assetType = (AssetType)im.binaryBucket[0];
479
480 if (AssetType.Folder == assetType)
484 { 481 {
485 AssetType assetType = (AssetType)im.binaryBucket[0]; 482 UUID folderID = new UUID(im.binaryBucket, 1);
486 UUID inventoryID = new UUID(im.binaryBucket, 1); 483
487 484 InventoryFolderBase folder =
488 IInventoryService invService = scene.InventoryService; 485 scene.InventoryService.GetFolder(recipientID, folderID);
489 InventoryNodeBase node = null; 486
490 if (AssetType.Folder == assetType) 487 if (folder != null)
488 user.ControllingClient.SendBulkUpdateInventory(folder);
489 }
490 else
491 {
492 UUID itemID = new UUID(im.binaryBucket, 1);
493
494 InventoryItemBase item =
495 scene.InventoryService.GetItem(recipientID, itemID);
496
497 if (item != null)
491 { 498 {
492 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, new UUID(im.toAgentID)); 499 user.ControllingClient.SendBulkUpdateInventory(item);
493 node = invService.GetFolder(folder);
494 } 500 }
495 else 501 }
502 user.ControllingClient.SendInstantMessage(im);
503 }
504 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
505 {
506 if (im.binaryBucket.Length < 1) // Invalid
507 return;
508
509 UUID recipientID = new UUID(im.toAgentID);
510
511 // Bucket is the asset type
512 AssetType assetType = (AssetType)im.binaryBucket[0];
513
514 if (AssetType.Folder == assetType)
515 {
516 UUID folderID = new UUID(im.imSessionID);
517
518 InventoryFolderBase folder =
519 scene.InventoryService.GetFolder(recipientID, folderID);
520
521 if (folder != null)
522 user.ControllingClient.SendBulkUpdateInventory(folder);
523 }
524 else
525 {
526 UUID itemID = new UUID(im.imSessionID);
527
528 InventoryItemBase item =
529 scene.InventoryService.GetItem(recipientID, itemID);
530
531 if (item != null)
496 { 532 {
497 InventoryItemBase item = new InventoryItemBase(inventoryID, new UUID(im.toAgentID)); 533 user.ControllingClient.SendBulkUpdateInventory(item);
498 node = invService.GetItem(item);
499 } 534 }
500
501 if (node != null)
502 user.ControllingClient.SendBulkUpdateInventory(node);
503 } 535 }
536
537 // Fix up binary bucket since this may be 17 chars long here
538 Byte[] bucket = new Byte[1];
539 bucket[0] = im.binaryBucket[0];
540 im.binaryBucket = bucket;
541
542 user.ControllingClient.SendInstantMessage(im);
543 }
544 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
545 im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
546 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined ||
547 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
548 {
549 user.ControllingClient.SendInstantMessage(im);
504 } 550 }
505 } 551 }
506 } 552 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
index 7ddc396..82ed091 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
@@ -44,9 +44,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class InventoryTransferModuleTests : OpenSimTestCase 46 public class InventoryTransferModuleTests : OpenSimTestCase
47 { 47 {
48 protected TestScene m_scene; 48 protected TestScene m_scene;
49 49
50 [SetUp] 50 [SetUp]
51 public override void SetUp() 51 public override void SetUp()
52 { 52 {
@@ -56,9 +56,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
56 config.AddConfig("Messaging"); 56 config.AddConfig("Messaging");
57 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule"); 57 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule");
58 58
59 m_scene = new SceneHelpers().SetupScene(); 59 m_scene = new SceneHelpers().SetupScene();
60 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule()); 60 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule());
61 } 61 }
62 62
63 [Test] 63 [Test]
64 public void TestAcceptGivenItem() 64 public void TestAcceptGivenItem()
@@ -69,9 +69,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
69 UUID itemId = TestHelpers.ParseTail(0x100); 69 UUID itemId = TestHelpers.ParseTail(0x100);
70 UUID assetId = TestHelpers.ParseTail(0x200); 70 UUID assetId = TestHelpers.ParseTail(0x200);
71 71
72 UserAccount ua1 72 UserAccount ua1
73 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 73 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
74 UserAccount ua2 74 UserAccount ua2
75 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 75 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
76 76
77 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 77 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
81 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 81 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
82 82
83 // Create the object to test give 83 // Create the object to test give
84 InventoryItemBase originalItem 84 InventoryItemBase originalItem
85 = UserInventoryHelpers.CreateInventoryItem( 85 = UserInventoryHelpers.CreateInventoryItem(
86 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); 86 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
87 87
@@ -89,35 +89,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
89 byte[] itemIdBytes = itemId.GetBytes(); 89 byte[] itemIdBytes = itemId.GetBytes();
90 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 90 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
91 91
92 GridInstantMessage giveIm 92 GridInstantMessage giveIm
93 = new GridInstantMessage( 93 = new GridInstantMessage(
94 m_scene, 94 m_scene,
95 giverSp.UUID, 95 giverSp.UUID,
96 giverSp.Name, 96 giverSp.Name,
97 receiverSp.UUID, 97 receiverSp.UUID,
98 (byte)InstantMessageDialog.InventoryOffered, 98 (byte)InstantMessageDialog.InventoryOffered,
99 false, 99 false,
100 "inventory offered msg", 100 "inventory offered msg",
101 initialSessionId, 101 initialSessionId,
102 false, 102 false,
103 Vector3.Zero, 103 Vector3.Zero,
104 giveImBinaryBucket, 104 giveImBinaryBucket,
105 true); 105 true);
106 106
107 giverClient.HandleImprovedInstantMessage(giveIm); 107 giverClient.HandleImprovedInstantMessage(giveIm);
108 108
109 // These details might not all be correct. 109 // These details might not all be correct.
110 GridInstantMessage acceptIm 110 GridInstantMessage acceptIm
111 = new GridInstantMessage( 111 = new GridInstantMessage(
112 m_scene, 112 m_scene,
113 receiverSp.UUID, 113 receiverSp.UUID,
114 receiverSp.Name, 114 receiverSp.Name,
115 giverSp.UUID, 115 giverSp.UUID,
116 (byte)InstantMessageDialog.InventoryAccepted, 116 (byte)InstantMessageDialog.InventoryAccepted,
117 false, 117 false,
118 "inventory accepted msg", 118 "inventory accepted msg",
119 initialSessionId, 119 initialSessionId,
120 false, 120 false,
121 Vector3.Zero, 121 Vector3.Zero,
122 null, 122 null,
123 true); 123 true);
@@ -133,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
133 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); 133 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
134 134
135 // Test for item successfully making it into the receiver's inventory 135 // Test for item successfully making it into the receiver's inventory
136 InventoryItemBase receivedItem 136 InventoryItemBase receivedItem
137 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj"); 137 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj");
138 138
139 Assert.That(receivedItem, Is.Not.Null); 139 Assert.That(receivedItem, Is.Not.Null);
@@ -148,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
148 Assert.That(originalItemAfterDelete, Is.Not.Null); 148 Assert.That(originalItemAfterDelete, Is.Not.Null);
149 149
150 // TODO: Test scenario where giver deletes their item first. 150 // TODO: Test scenario where giver deletes their item first.
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// Test user rejection of a given item. 154 /// Test user rejection of a given item.
@@ -165,9 +165,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
165 UUID itemId = TestHelpers.ParseTail(0x100); 165 UUID itemId = TestHelpers.ParseTail(0x100);
166 UUID assetId = TestHelpers.ParseTail(0x200); 166 UUID assetId = TestHelpers.ParseTail(0x200);
167 167
168 UserAccount ua1 168 UserAccount ua1
169 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 169 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
170 UserAccount ua2 170 UserAccount ua2
171 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 171 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
172 172
173 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 173 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -177,7 +177,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
177 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 177 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
178 178
179 // Create the object to test give 179 // Create the object to test give
180 InventoryItemBase originalItem 180 InventoryItemBase originalItem
181 = UserInventoryHelpers.CreateInventoryItem( 181 = UserInventoryHelpers.CreateInventoryItem(
182 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); 182 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
183 183
@@ -188,36 +188,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
188 byte[] itemIdBytes = itemId.GetBytes(); 188 byte[] itemIdBytes = itemId.GetBytes();
189 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 189 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
190 190
191 GridInstantMessage giveIm 191 GridInstantMessage giveIm
192 = new GridInstantMessage( 192 = new GridInstantMessage(
193 m_scene, 193 m_scene,
194 giverSp.UUID, 194 giverSp.UUID,
195 giverSp.Name, 195 giverSp.Name,
196 receiverSp.UUID, 196 receiverSp.UUID,
197 (byte)InstantMessageDialog.InventoryOffered, 197 (byte)InstantMessageDialog.InventoryOffered,
198 false, 198 false,
199 "inventory offered msg", 199 "inventory offered msg",
200 initialSessionId, 200 initialSessionId,
201 false, 201 false,
202 Vector3.Zero, 202 Vector3.Zero,
203 giveImBinaryBucket, 203 giveImBinaryBucket,
204 true); 204 true);
205 205
206 giverClient.HandleImprovedInstantMessage(giveIm); 206 giverClient.HandleImprovedInstantMessage(giveIm);
207 207
208 // These details might not all be correct. 208 // These details might not all be correct.
209 // Session ID is now the created item ID (!) 209 // Session ID is now the created item ID (!)
210 GridInstantMessage rejectIm 210 GridInstantMessage rejectIm
211 = new GridInstantMessage( 211 = new GridInstantMessage(
212 m_scene, 212 m_scene,
213 receiverSp.UUID, 213 receiverSp.UUID,
214 receiverSp.Name, 214 receiverSp.Name,
215 giverSp.UUID, 215 giverSp.UUID,
216 (byte)InstantMessageDialog.InventoryDeclined, 216 (byte)InstantMessageDialog.InventoryDeclined,
217 false, 217 false,
218 "inventory declined msg", 218 "inventory declined msg",
219 new UUID(receivedIm.imSessionID), 219 new UUID(receivedIm.imSessionID),
220 false, 220 false,
221 Vector3.Zero, 221 Vector3.Zero,
222 null, 222 null,
223 true); 223 true);
@@ -233,7 +233,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
233 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); 233 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
234 234
235 // Test for item successfully making it into the receiver's inventory 235 // Test for item successfully making it into the receiver's inventory
236 InventoryItemBase receivedItem 236 InventoryItemBase receivedItem
237 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj"); 237 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj");
238 238
239 InventoryFolderBase trashFolder 239 InventoryFolderBase trashFolder
@@ -250,7 +250,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
250 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); 250 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
251 251
252 Assert.That(originalItemAfterDelete, Is.Not.Null); 252 Assert.That(originalItemAfterDelete, Is.Not.Null);
253 } 253 }
254 254
255 [Test] 255 [Test]
256 public void TestAcceptGivenFolder() 256 public void TestAcceptGivenFolder()
@@ -261,9 +261,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
261 UUID initialSessionId = TestHelpers.ParseTail(0x10); 261 UUID initialSessionId = TestHelpers.ParseTail(0x10);
262 UUID folderId = TestHelpers.ParseTail(0x100); 262 UUID folderId = TestHelpers.ParseTail(0x100);
263 263
264 UserAccount ua1 264 UserAccount ua1
265 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 265 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
266 UserAccount ua2 266 UserAccount ua2
267 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 267 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
268 268
269 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 269 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -272,7 +272,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
272 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); 272 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
273 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 273 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
274 274
275 InventoryFolderBase originalFolder 275 InventoryFolderBase originalFolder
276 = UserInventoryHelpers.CreateInventoryFolder( 276 = UserInventoryHelpers.CreateInventoryFolder(
277 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); 277 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
278 278
@@ -281,35 +281,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
281 byte[] itemIdBytes = folderId.GetBytes(); 281 byte[] itemIdBytes = folderId.GetBytes();
282 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 282 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
283 283
284 GridInstantMessage giveIm 284 GridInstantMessage giveIm
285 = new GridInstantMessage( 285 = new GridInstantMessage(
286 m_scene, 286 m_scene,
287 giverSp.UUID, 287 giverSp.UUID,
288 giverSp.Name, 288 giverSp.Name,
289 receiverSp.UUID, 289 receiverSp.UUID,
290 (byte)InstantMessageDialog.InventoryOffered, 290 (byte)InstantMessageDialog.InventoryOffered,
291 false, 291 false,
292 "inventory offered msg", 292 "inventory offered msg",
293 initialSessionId, 293 initialSessionId,
294 false, 294 false,
295 Vector3.Zero, 295 Vector3.Zero,
296 giveImBinaryBucket, 296 giveImBinaryBucket,
297 true); 297 true);
298 298
299 giverClient.HandleImprovedInstantMessage(giveIm); 299 giverClient.HandleImprovedInstantMessage(giveIm);
300 300
301 // These details might not all be correct. 301 // These details might not all be correct.
302 GridInstantMessage acceptIm 302 GridInstantMessage acceptIm
303 = new GridInstantMessage( 303 = new GridInstantMessage(
304 m_scene, 304 m_scene,
305 receiverSp.UUID, 305 receiverSp.UUID,
306 receiverSp.Name, 306 receiverSp.Name,
307 giverSp.UUID, 307 giverSp.UUID,
308 (byte)InstantMessageDialog.InventoryAccepted, 308 (byte)InstantMessageDialog.InventoryAccepted,
309 false, 309 false,
310 "inventory accepted msg", 310 "inventory accepted msg",
311 initialSessionId, 311 initialSessionId,
312 false, 312 false,
313 Vector3.Zero, 313 Vector3.Zero,
314 null, 314 null,
315 true); 315 true);
@@ -325,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
325 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); 325 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
326 326
327 // Test for item successfully making it into the receiver's inventory 327 // Test for item successfully making it into the receiver's inventory
328 InventoryFolderBase receivedFolder 328 InventoryFolderBase receivedFolder
329 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1"); 329 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1");
330 330
331 Assert.That(receivedFolder, Is.Not.Null); 331 Assert.That(receivedFolder, Is.Not.Null);
@@ -340,7 +340,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
340 Assert.That(originalFolderAfterDelete, Is.Not.Null); 340 Assert.That(originalFolderAfterDelete, Is.Not.Null);
341 341
342 // TODO: Test scenario where giver deletes their item first. 342 // TODO: Test scenario where giver deletes their item first.
343 } 343 }
344 344
345 /// <summary> 345 /// <summary>
346 /// Test user rejection of a given item. 346 /// Test user rejection of a given item.
@@ -357,9 +357,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
357 UUID initialSessionId = TestHelpers.ParseTail(0x10); 357 UUID initialSessionId = TestHelpers.ParseTail(0x10);
358 UUID folderId = TestHelpers.ParseTail(0x100); 358 UUID folderId = TestHelpers.ParseTail(0x100);
359 359
360 UserAccount ua1 360 UserAccount ua1
361 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); 361 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
362 UserAccount ua2 362 UserAccount ua2
363 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); 363 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
364 364
365 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); 365 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
@@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
369 TestClient receiverClient = (TestClient)receiverSp.ControllingClient; 369 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
370 370
371 // Create the folder to test give 371 // Create the folder to test give
372 InventoryFolderBase originalFolder 372 InventoryFolderBase originalFolder
373 = UserInventoryHelpers.CreateInventoryFolder( 373 = UserInventoryHelpers.CreateInventoryFolder(
374 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); 374 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
375 375
@@ -381,36 +381,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
381 byte[] itemIdBytes = folderId.GetBytes(); 381 byte[] itemIdBytes = folderId.GetBytes();
382 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); 382 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
383 383
384 GridInstantMessage giveIm 384 GridInstantMessage giveIm
385 = new GridInstantMessage( 385 = new GridInstantMessage(
386 m_scene, 386 m_scene,
387 giverSp.UUID, 387 giverSp.UUID,
388 giverSp.Name, 388 giverSp.Name,
389 receiverSp.UUID, 389 receiverSp.UUID,
390 (byte)InstantMessageDialog.InventoryOffered, 390 (byte)InstantMessageDialog.InventoryOffered,
391 false, 391 false,
392 "inventory offered msg", 392 "inventory offered msg",
393 initialSessionId, 393 initialSessionId,
394 false, 394 false,
395 Vector3.Zero, 395 Vector3.Zero,
396 giveImBinaryBucket, 396 giveImBinaryBucket,
397 true); 397 true);
398 398
399 giverClient.HandleImprovedInstantMessage(giveIm); 399 giverClient.HandleImprovedInstantMessage(giveIm);
400 400
401 // These details might not all be correct. 401 // These details might not all be correct.
402 // Session ID is now the created item ID (!) 402 // Session ID is now the created item ID (!)
403 GridInstantMessage rejectIm 403 GridInstantMessage rejectIm
404 = new GridInstantMessage( 404 = new GridInstantMessage(
405 m_scene, 405 m_scene,
406 receiverSp.UUID, 406 receiverSp.UUID,
407 receiverSp.Name, 407 receiverSp.Name,
408 giverSp.UUID, 408 giverSp.UUID,
409 (byte)InstantMessageDialog.InventoryDeclined, 409 (byte)InstantMessageDialog.InventoryDeclined,
410 false, 410 false,
411 "inventory declined msg", 411 "inventory declined msg",
412 new UUID(receivedIm.imSessionID), 412 new UUID(receivedIm.imSessionID),
413 false, 413 false,
414 Vector3.Zero, 414 Vector3.Zero,
415 null, 415 null,
416 true); 416 true);
@@ -426,7 +426,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
426 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); 426 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
427 427
428 // Test for folder successfully making it into the receiver's inventory 428 // Test for folder successfully making it into the receiver's inventory
429 InventoryFolderBase receivedFolder 429 InventoryFolderBase receivedFolder
430 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1"); 430 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1");
431 431
432 InventoryFolderBase trashFolder 432 InventoryFolderBase trashFolder
@@ -443,6 +443,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
443 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); 443 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
444 444
445 Assert.That(originalFolderAfterDelete, Is.Not.Null); 445 Assert.That(originalFolderAfterDelete, Is.Not.Null);
446 } 446 }
447 } 447 }
448} \ No newline at end of file 448} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 24286a4..3dc9bf5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -29,10 +29,9 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using Mono.Addins;
35
36using OpenSim.Framework; 35using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
@@ -45,13 +44,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGLureModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGLureModule")]
46 public class HGLureModule : ISharedRegionModule 45 public class HGLureModule : ISharedRegionModule
47 { 46 {
48 private static readonly ILog m_log = LogManager.GetLogger( 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 MethodBase.GetCurrentMethod().DeclaringType);
50 48
51 private readonly List<Scene> m_scenes = new List<Scene>(); 49 private readonly List<Scene> m_scenes = new List<Scene>();
52 50
53 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule = null;
54 private bool m_Enabled = false;
55 52
56 private string m_ThisGridURL; 53 private string m_ThisGridURL;
57 54
@@ -61,24 +58,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
61 { 58 {
62 if (config.Configs["Messaging"] != null) 59 if (config.Configs["Messaging"] != null)
63 { 60 {
64 if (config.Configs["Messaging"].GetString("LureModule", string.Empty) == "HGLureModule") 61 m_ThisGridURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI", new string[] { "Startup", "Hypergrid", "Messaging" }, String.Empty);
65 { 62 // Legacy. Remove soon!
66 m_Enabled = true; 63//// m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL);
67 64 m_log.DebugFormat("[HG LURE MODULE]: {0} enabled", Name);
68 m_ThisGridURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
69 new string[] { "Startup", "Hypergrid", "Messaging" }, String.Empty);
70 // Legacy. Remove soon!
71 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL);
72 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
73 }
74 } 65 }
75 } 66 }
76 67
77 public void AddRegion(Scene scene) 68 public void AddRegion(Scene scene)
78 { 69 {
79 if (!m_Enabled)
80 return;
81
82 lock (m_scenes) 70 lock (m_scenes)
83 { 71 {
84 m_scenes.Add(scene); 72 m_scenes.Add(scene);
@@ -89,9 +77,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
89 77
90 public void RegionLoaded(Scene scene) 78 public void RegionLoaded(Scene scene)
91 { 79 {
92 if (!m_Enabled)
93 return;
94
95 if (m_TransferModule == null) 80 if (m_TransferModule == null)
96 { 81 {
97 m_TransferModule = 82 m_TransferModule =
@@ -99,9 +84,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
99 84
100 if (m_TransferModule == null) 85 if (m_TransferModule == null)
101 { 86 {
102 m_log.Error("[LURE MODULE]: No message transfer module, lures will not work!"); 87 m_log.Error("[HG LURE MODULE]: No message transfer module, lures will not work!");
103
104 m_Enabled = false;
105 m_scenes.Clear(); 88 m_scenes.Clear();
106 scene.EventManager.OnNewClient -= OnNewClient; 89 scene.EventManager.OnNewClient -= OnNewClient;
107 scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage; 90 scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage;
@@ -112,9 +95,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
112 95
113 public void RemoveRegion(Scene scene) 96 public void RemoveRegion(Scene scene)
114 { 97 {
115 if (!m_Enabled)
116 return;
117
118 lock (m_scenes) 98 lock (m_scenes)
119 { 99 {
120 m_scenes.Remove(scene); 100 m_scenes.Remove(scene);
@@ -154,19 +134,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
154 134
155 void OnIncomingInstantMessage(GridInstantMessage im) 135 void OnIncomingInstantMessage(GridInstantMessage im)
156 { 136 {
157 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport 137 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport || im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport)
158 || im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport)
159 { 138 {
160 UUID sessionID = new UUID(im.imSessionID); 139 UUID sessionID = new UUID(im.imSessionID);
161
162 if (!m_PendingLures.Contains(sessionID)) 140 if (!m_PendingLures.Contains(sessionID))
163 { 141 {
164 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); 142 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message);
165 m_PendingLures.Add(sessionID, im, 7200); // 2 hours 143 m_PendingLures.Add(sessionID, im, 7200); // 2 hours
166 } 144 }
167 145 // Forward. We do this, because the IM module explicitly rejects IMs of this type
168 // Forward. We do this, because the IM module explicitly rejects
169 // IMs of this type
170 if (m_TransferModule != null) 146 if (m_TransferModule != null)
171 m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); 147 m_TransferModule.SendInstantMessage(im, delegate(bool success) { });
172 } 148 }
@@ -179,23 +155,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
179 155
180 Scene scene = (Scene)(client.Scene); 156 Scene scene = (Scene)(client.Scene);
181 ScenePresence presence = scene.GetScenePresence(client.AgentId); 157 ScenePresence presence = scene.GetScenePresence(client.AgentId);
158 ScenePresence target = scene.GetScenePresence(targetid);
159 Guid start = client.Scene.RegionInfo.RegionID.Guid;
160 UUID dest = UUID.Random();
161 byte reqType = (byte)InstantMessageDialog.RequestTeleport;
162 GridInstantMessage m;
182 163
183 message += "@" + m_ThisGridURL; 164 GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(start));
184 165 if (region != null)
185 m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); 166 {
186 167 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.IsViewerUIGod && (!scene.Permissions.IsAdministrator(targetid)))
187 UUID sessionID = UUID.Random(); 168 {
169 reqType = (byte)InstantMessageDialog.GodLikeRequestTeleport;
170 m_log.DebugFormat("[HG LURE MODULE]: TP FORCE GOD LURE with message {0}, type {1}", message, lureType);
171 }
172 else
173 m_log.DebugFormat("[HG LURE MODULE]: TP lure with message {0}, type {1}", message, lureType);
174 }
175 else
176 {
177 m_log.DebugFormat("[HG LURE MODULE]: hypergrid TP lure with message {0}, type {1}", message, lureType);
178 message += "@" + m_ThisGridURL;
179 }
188 180
189 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, 181 m = new GridInstantMessage(scene, client.AgentId, client.FirstName+" "+client.LastName, targetid,
190 client.FirstName+" "+client.LastName, targetid, 182 reqType, false, message, dest, false, presence.AbsolutePosition, new Byte[0], true);
191 (byte)InstantMessageDialog.RequestTeleport, false, 183 m.RegionID = start;
192 message, sessionID, false, presence.AbsolutePosition, 184 m_PendingLures.Add(dest, m, 7200); // 2 hours
193 new Byte[0], true);
194 m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
195 185
196 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
197 m_PendingLures.Add(sessionID, m, 7200); // 2 hours
198
199 if (m_TransferModule != null) 186 if (m_TransferModule != null)
200 { 187 {
201 m_TransferModule.SendInstantMessage(m, 188 m_TransferModule.SendInstantMessage(m,
@@ -208,64 +195,56 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
208 if (!(client.Scene is Scene)) 195 if (!(client.Scene is Scene))
209 return; 196 return;
210 197
211// Scene scene = (Scene)(client.Scene); 198 Scene scene = (Scene)(client.Scene);
212
213 GridInstantMessage im = null; 199 GridInstantMessage im = null;
200
214 if (m_PendingLures.TryGetValue(lureID, out im)) 201 if (m_PendingLures.TryGetValue(lureID, out im))
215 { 202 {
203 im.Position = im.Position + new Vector3(0.5f, 0.5f, 2f);
216 m_PendingLures.Remove(lureID); 204 m_PendingLures.Remove(lureID);
217 Lure(client, teleportFlags, im); 205 GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(im.RegionID));
218 } 206 if (region != null)
219 else 207 scene.RequestTeleportLocation(client, region.RegionHandle, im.Position, Vector3.UnitX, teleportFlags);
220 m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID); 208 else // we don't have that region here. Check if it's HG
221
222 }
223
224 private void Lure(IClientAPI client, uint teleportflags, GridInstantMessage im)
225 {
226 Scene scene = (Scene)(client.Scene);
227 GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(im.RegionID));
228 if (region != null)
229 scene.RequestTeleportLocation(client, region.RegionHandle, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags);
230 else // we don't have that region here. Check if it's HG
231 {
232 string[] parts = im.message.Split(new char[] { '@' });
233 if (parts.Length > 1)
234 { 209 {
235 string url = parts[parts.Length - 1]; // the last part 210 string[] parts = im.message.Split(new char[] { '@' });
236 if (url.Trim(new char[] {'/'}) != m_ThisGridURL.Trim(new char[] {'/'})) 211 if (parts.Length > 1)
237 { 212 {
238 m_log.DebugFormat("[HG LURE MODULE]: Luring agent to grid {0} region {1} position {2}", url, im.RegionID, im.Position); 213 string url = parts[parts.Length - 1]; // the last part
239 GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); 214 if (url.Trim(new char[] {'/'}) != m_ThisGridURL.Trim(new char[] {'/'}))
240 GridRegion gatekeeper = new GridRegion();
241 gatekeeper.ServerURI = url;
242 string homeURI = scene.GetAgentHomeURI(client.AgentId);
243
244 string message;
245 GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(im.RegionID), client.AgentId, homeURI, out message);
246 if (finalDestination != null)
247 { 215 {
248 ScenePresence sp = scene.GetScenePresence(client.AgentId); 216 m_log.DebugFormat("[HG LURE MODULE]: Luring agent to remote grid {0} region {1} position {2}", url, im.RegionID, im.Position);
249 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>(); 217 GatekeeperServiceConnector gConn = new GatekeeperServiceConnector();
250 218 GridRegion gatekeeper = new GridRegion();
251 if (transferMod != null && sp != null) 219 gatekeeper.ServerURI = url;
220 string homeURI = scene.GetAgentHomeURI(client.AgentId);
221
222 string message;
223 GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(im.RegionID), client.AgentId, homeURI, out message);
224 if (finalDestination != null)
252 { 225 {
253 if (message != null) 226 ScenePresence sp = scene.GetScenePresence(client.AgentId);
254 sp.ControllingClient.SendAgentAlertMessage(message, true); 227 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
228
229 if (transferMod != null && sp != null)
230 {
231 if (message != null)
232 sp.ControllingClient.SendAgentAlertMessage(message, true);
255 233
256 transferMod.DoTeleport( 234 transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position, Vector3.UnitX, teleportFlags);
257 sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), 235 }
258 Vector3.UnitX, teleportflags); 236 }
237 else
238 {
239 m_log.InfoFormat("[HG LURE MODULE]: Lure failed: {0}", message);
240 client.SendAgentAlertMessage(message, true);
259 } 241 }
260 }
261 else
262 {
263 m_log.InfoFormat("[HG LURE MODULE]: Lure failed: {0}", message);
264 client.SendAgentAlertMessage(message, true);
265 } 242 }
266 } 243 }
267 } 244 }
268 } 245 }
246 else
247 m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID);
269 } 248 }
270 } 249 }
271} \ No newline at end of file 250}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
deleted file mode 100644
index 465ffbc..0000000
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ /dev/null
@@ -1,220 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38
39namespace OpenSim.Region.CoreModules.Avatar.Lure
40{
41 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LureModule")]
42 public class LureModule : ISharedRegionModule
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType);
46
47 private readonly List<Scene> m_scenes = new List<Scene>();
48
49 private IMessageTransferModule m_TransferModule = null;
50 private bool m_Enabled = false;
51
52 public void Initialise(IConfigSource config)
53 {
54 if (config.Configs["Messaging"] != null)
55 {
56 if (config.Configs["Messaging"].GetString(
57 "LureModule", "LureModule") ==
58 "LureModule")
59 {
60 m_Enabled = true;
61 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
62 }
63 }
64 }
65
66 public void AddRegion(Scene scene)
67 {
68 if (!m_Enabled)
69 return;
70
71 lock (m_scenes)
72 {
73 m_scenes.Add(scene);
74 scene.EventManager.OnNewClient += OnNewClient;
75 scene.EventManager.OnIncomingInstantMessage +=
76 OnGridInstantMessage;
77 }
78 }
79
80 public void RegionLoaded(Scene scene)
81 {
82 if (!m_Enabled)
83 return;
84
85 if (m_TransferModule == null)
86 {
87 m_TransferModule =
88 scene.RequestModuleInterface<IMessageTransferModule>();
89
90 if (m_TransferModule == null)
91 {
92 m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+
93 "lures will not work!");
94
95 m_Enabled = false;
96 m_scenes.Clear();
97 scene.EventManager.OnNewClient -= OnNewClient;
98 scene.EventManager.OnIncomingInstantMessage -=
99 OnGridInstantMessage;
100 }
101 }
102
103 }
104
105 public void RemoveRegion(Scene scene)
106 {
107 if (!m_Enabled)
108 return;
109
110 lock (m_scenes)
111 {
112 m_scenes.Remove(scene);
113 scene.EventManager.OnNewClient -= OnNewClient;
114 scene.EventManager.OnIncomingInstantMessage -=
115 OnGridInstantMessage;
116 }
117 }
118
119 void OnNewClient(IClientAPI client)
120 {
121 client.OnInstantMessage += OnInstantMessage;
122 client.OnStartLure += OnStartLure;
123 client.OnTeleportLureRequest += OnTeleportLureRequest;
124 }
125
126 public void PostInitialise()
127 {
128 }
129
130 public void Close()
131 {
132 }
133
134 public string Name
135 {
136 get { return "LureModule"; }
137 }
138
139 public Type ReplaceableInterface
140 {
141 get { return null; }
142 }
143
144 public void OnInstantMessage(IClientAPI client, GridInstantMessage im)
145 {
146 }
147
148 public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client)
149 {
150 if (!(client.Scene is Scene))
151 return;
152
153 Scene scene = (Scene)(client.Scene);
154 ScenePresence presence = scene.GetScenePresence(client.AgentId);
155
156 // Round up Z co-ordinate rather than round-down by casting. This stops tall avatars from being given
157 // a teleport Z co-ordinate by short avatars that drops them through or embeds them in thin floors on
158 // arrival.
159 //
160 // Ideally we would give the exact float position adjusting for the relative height of the two avatars
161 // but it looks like a float component isn't possible with a parcel ID.
162 UUID dest = Util.BuildFakeParcelID(
163 scene.RegionInfo.RegionHandle,
164 (uint)presence.AbsolutePosition.X,
165 (uint)presence.AbsolutePosition.Y,
166 (uint)Math.Ceiling(presence.AbsolutePosition.Z));
167
168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169
170 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
171 client.FirstName+" "+client.LastName, targetid,
172 (byte)InstantMessageDialog.RequestTeleport, false,
173 message, dest, false, presence.AbsolutePosition,
174 new Byte[0], true);
175
176 if (m_TransferModule != null)
177 {
178 m_TransferModule.SendInstantMessage(m,
179 delegate(bool success) { });
180 }
181 }
182
183 public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client)
184 {
185 if (!(client.Scene is Scene))
186 return;
187
188 Scene scene = (Scene)(client.Scene);
189
190 ulong handle = 0;
191 uint x = 128;
192 uint y = 128;
193 uint z = 70;
194
195 Util.ParseFakeParcelID(lureID, out handle, out x, out y, out z);
196
197 Vector3 position = new Vector3();
198 position.X = (float)x;
199 position.Y = (float)y;
200 position.Z = (float)z;
201
202 scene.RequestTeleportLocation(client, handle, position,
203 Vector3.Zero, teleportFlags);
204 }
205
206 private void OnGridInstantMessage(GridInstantMessage msg)
207 {
208 // Forward remote teleport requests
209 //
210 if (msg.dialog != 22)
211 return;
212
213 if (m_TransferModule != null)
214 {
215 m_TransferModule.SendInstantMessage(msg,
216 delegate(bool success) { });
217 }
218 }
219 }
220}
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index 2bb24ae..1e1caca 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
68 { 68 {
69 if (!m_Enabled) 69 if (!m_Enabled)
70 return; 70 return;
71 71
72 lock (m_Scenes) 72 lock (m_Scenes)
73 { 73 {
74 if (!m_Scenes.Contains(scene)) 74 if (!m_Scenes.Contains(scene))
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
154 name = account.FirstName + " " + account.LastName; 154 name = account.FirstName + " " + account.LastName;
155 created = account.Created; 155 created = account.Created;
156 } 156 }
157 Byte[] charterMember = Utils.StringToBytes(name); 157 Byte[] membershipType = Utils.StringToBytes(name);
158 158
159 profileUrl = "No profile data"; 159 profileUrl = "No profile data";
160 aboutText = string.Empty; 160 aboutText = string.Empty;
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
166 remoteClient.SendAvatarProperties(avatarID, aboutText, 166 remoteClient.SendAvatarProperties(avatarID, aboutText,
167 Util.ToDateTime(created).ToString( 167 Util.ToDateTime(created).ToString(
168 "M/d/yyyy", CultureInfo.InvariantCulture), 168 "M/d/yyyy", CultureInfo.InvariantCulture),
169 charterMember, firstLifeAboutText, 169 membershipType, firstLifeAboutText,
170 (uint)(0 & 0xff), 170 (uint)(0 & 0xff),
171 firstLifeImage, image, profileUrl, partner); 171 firstLifeImage, image, profileUrl, partner);
172 172
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index c20369c..b25ef58 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -31,6 +31,7 @@ using System.Text;
31using System.Collections; 31using System.Collections;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Globalization; 33using System.Globalization;
34using System.Linq;
34using System.Net; 35using System.Net;
35using System.Net.Sockets; 36using System.Net.Sockets;
36using System.Reflection; 37using System.Reflection;
@@ -56,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")] 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
57 public class UserProfileModule : IProfileModule, INonSharedRegionModule 58 public class UserProfileModule : IProfileModule, INonSharedRegionModule
58 { 59 {
60 const double PROFILECACHEEXPIRE = 300;
59 /// <summary> 61 /// <summary>
60 /// Logging 62 /// Logging
61 /// </summary> 63 /// </summary>
@@ -66,8 +68,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
66 // count. The entries are removed when the interest count reaches 0. 68 // count. The entries are removed when the interest count reaches 0.
67 Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>(); 69 Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>();
68 Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>(); 70 Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>();
71 ExpiringCache<UUID, UserProfileCacheEntry> m_profilesCache = new ExpiringCache<UUID, UserProfileCacheEntry>();
72 IAssetCache m_assetCache;
69 73
70 private JsonRpcRequestManager rpc = new JsonRpcRequestManager(); 74 private JsonRpcRequestManager rpc = new JsonRpcRequestManager();
75 private bool m_allowUserProfileWebURLs = true;
71 76
72 public Scene Scene 77 public Scene Scene
73 { 78 {
@@ -80,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
80 /// <value> 85 /// <value>
81 /// The configuration 86 /// The configuration
82 /// </value> 87 /// </value>
83 public IConfigSource Config 88 public IConfigSource Config
84 { 89 {
85 get; 90 get;
86 set; 91 set;
@@ -92,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
92 /// <value> 97 /// <value>
93 /// The profile server URI. 98 /// The profile server URI.
94 /// </value> 99 /// </value>
95 public string ProfileServerUri 100 public string ProfileServerUri
96 { 101 {
97 get; 102 get;
98 set; 103 set;
@@ -115,23 +120,22 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
115 /// <value> 120 /// <value>
116 /// <c>true</c> if enabled; otherwise, <c>false</c>. 121 /// <c>true</c> if enabled; otherwise, <c>false</c>.
117 /// </value> 122 /// </value>
118 public bool Enabled 123 public bool Enabled
119 { 124 {
120 get; 125 get;
121 set; 126 set;
122 } 127 }
123 128
124 public string MyGatekeeper 129 public string MyGatekeeper
125 { 130 {
126 get; private set; 131 get; private set;
127 } 132 }
128 133
129
130 #region IRegionModuleBase implementation 134 #region IRegionModuleBase implementation
131 /// <summary> 135 /// <summary>
132 /// This is called to initialize the region module. For shared modules, this is called exactly once, after 136 /// This is called to initialize the region module. For shared modules, this is called exactly once, after
133 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after 137 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
134 /// the instace for the region has been created. 138 /// the instace for the region has been created.
135 /// </summary> 139 /// </summary>
136 /// <param name='source'> 140 /// <param name='source'>
137 /// Source. 141 /// Source.
@@ -145,12 +149,12 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
145 149
146 if (profileConfig == null) 150 if (profileConfig == null)
147 { 151 {
148 m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration"); 152 //m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration");
149 Enabled = false; 153 Enabled = false;
150 return; 154 return;
151 } 155 }
152 156
153 // If we find ProfileURL then we configure for FULL support 157 // If we find ProfileServiceURL then we configure for FULL support
154 // else we setup for BASIC support 158 // else we setup for BASIC support
155 ProfileServerUri = profileConfig.GetString("ProfileServiceURL", ""); 159 ProfileServerUri = profileConfig.GetString("ProfileServiceURL", "");
156 if (ProfileServerUri == "") 160 if (ProfileServerUri == "")
@@ -158,7 +162,9 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
158 Enabled = false; 162 Enabled = false;
159 return; 163 return;
160 } 164 }
161 165
166 m_allowUserProfileWebURLs = profileConfig.GetBoolean("AllowUserProfileWebURLs", m_allowUserProfileWebURLs);
167
162 m_log.Debug("[PROFILES]: Full Profiles Enabled"); 168 m_log.Debug("[PROFILES]: Full Profiles Enabled");
163 ReplaceableInterface = null; 169 ReplaceableInterface = null;
164 Enabled = true; 170 Enabled = true;
@@ -181,22 +187,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
181 Scene = scene; 187 Scene = scene;
182 Scene.RegisterModuleInterface<IProfileModule>(this); 188 Scene.RegisterModuleInterface<IProfileModule>(this);
183 Scene.EventManager.OnNewClient += OnNewClient; 189 Scene.EventManager.OnNewClient += OnNewClient;
184 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent; 190 Scene.EventManager.OnClientClosed += OnClientClosed;
185 191
186 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>(); 192 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
187 } 193 }
188 194
189 void HandleOnMakeRootAgent (ScenePresence obj)
190 {
191 if(obj.PresenceType == PresenceType.Npc)
192 return;
193
194 Util.FireAndForget(delegate
195 {
196 GetImageAssets(((IScenePresence)obj).UUID);
197 }, null, "UserProfileModule.GetImageAssets");
198 }
199
200 /// <summary> 195 /// <summary>
201 /// Removes the region. 196 /// Removes the region.
202 /// </summary> 197 /// </summary>
@@ -207,13 +202,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
207 { 202 {
208 if(!Enabled) 203 if(!Enabled)
209 return; 204 return;
205
206 m_profilesCache.Clear();
207 m_classifiedCache.Clear();
208 m_classifiedInterest.Clear();
210 } 209 }
211 210
212 /// <summary> 211 /// <summary>
213 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one 212 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
214 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion 213 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
215 /// has been called in all modules for that scene, providing an opportunity to request another module's 214 /// has been called in all modules for that scene, providing an opportunity to request another module's
216 /// interface, or hook an event from another module. 215 /// interface, or hook an event from another module.
217 /// </summary> 216 /// </summary>
218 /// <param name='scene'> 217 /// <param name='scene'>
219 /// Scene. 218 /// Scene.
@@ -222,6 +221,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
222 { 221 {
223 if(!Enabled) 222 if(!Enabled)
224 return; 223 return;
224 m_assetCache = Scene.RequestModuleInterface<IAssetCache>();
225 } 225 }
226 226
227 /// <summary> 227 /// <summary>
@@ -230,7 +230,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
230 /// module has registered the interface by then, this module will be activated, else it will remain inactive, 230 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
231 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be 231 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
232 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party 232 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
233 /// provided modules. 233 /// provided modules.
234 /// </summary> 234 /// </summary>
235 /// <value> 235 /// <value>
236 /// The replaceable interface. 236 /// The replaceable interface.
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
248 } 248 }
249 249
250 /// <value> 250 /// <value>
251 /// The name of the module 251 /// The name of the module
252 /// </value> 252 /// </value>
253 /// <summary> 253 /// <summary>
254 /// Gets the module name. 254 /// Gets the module name.
@@ -293,6 +293,40 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
293 client.OnUserInfoRequest += UserPreferencesRequest; 293 client.OnUserInfoRequest += UserPreferencesRequest;
294 client.OnUpdateUserInfo += UpdateUserPreferences; 294 client.OnUpdateUserInfo += UpdateUserPreferences;
295 } 295 }
296
297 void OnClientClosed(UUID AgentId, Scene scene)
298 {
299 ScenePresence sp = scene.GetScenePresence(AgentId);
300 IClientAPI client = sp.ControllingClient;
301 if (client == null)
302 return;
303
304 //Profile
305 client.OnRequestAvatarProperties -= RequestAvatarProperties;
306 client.OnUpdateAvatarProperties -= AvatarPropertiesUpdate;
307 client.OnAvatarInterestUpdate -= AvatarInterestsUpdate;
308
309 // Classifieds
310// client.r GenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
311 client.OnClassifiedInfoUpdate -= ClassifiedInfoUpdate;
312 client.OnClassifiedInfoRequest -= ClassifiedInfoRequest;
313 client.OnClassifiedDelete -= ClassifiedDelete;
314
315 // Picks
316// client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
317// client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
318 client.OnPickInfoUpdate -= PickInfoUpdate;
319 client.OnPickDelete -= PickDelete;
320
321 // Notes
322// client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
323 client.OnAvatarNotesUpdate -= NotesUpdate;
324
325 // Preferences
326 client.OnUserInfoRequest -= UserPreferencesRequest;
327 client.OnUpdateUserInfo -= UpdateUserPreferences;
328 }
329
296 #endregion Region Event Handlers 330 #endregion Region Event Handlers
297 331
298 #region Classified 332 #region Classified
@@ -315,38 +349,74 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
315 return; 349 return;
316 350
317 IClientAPI remoteClient = (IClientAPI)sender; 351 IClientAPI remoteClient = (IClientAPI)sender;
352 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
318 353
319 UUID targetID; 354 UUID targetID;
320 UUID.TryParse(args[0], out targetID); 355 if(!UUID.TryParse(args[0], out targetID) || targetID == UUID.Zero)
356 return;
321 357
322 // Can't handle NPC yet...
323 ScenePresence p = FindPresence(targetID); 358 ScenePresence p = FindPresence(targetID);
359 if (p != null && p.IsNPC)
360 {
361 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
362 return;
363 }
324 364
325 if (null != p) 365 UserProfileCacheEntry uce = null;
366 lock(m_profilesCache)
326 { 367 {
327 if (p.PresenceType == PresenceType.Npc) 368 if(m_profilesCache.TryGetValue(targetID, out uce) && uce != null)
328 return; 369 {
370 if(uce.classifiedsLists != null)
371 {
372 foreach(KeyValuePair<UUID,string> kvp in uce.classifiedsLists)
373 {
374 UUID kvpkey = kvp.Key;
375 classifieds[kvpkey] = kvp.Value;
376 lock (m_classifiedCache)
377 {
378 if (!m_classifiedCache.ContainsKey(kvpkey))
379 {
380 m_classifiedCache.Add(kvpkey,targetID);
381 m_classifiedInterest.Add(kvpkey, 0);
382 }
383
384 m_classifiedInterest[kvpkey]++;
385 }
386 }
387 remoteClient.SendAvatarClassifiedReply(targetID, uce.classifiedsLists);
388 return;
389 }
390 }
329 } 391 }
330 392
331 string serverURI = string.Empty; 393 string serverURI = string.Empty;
332 GetUserProfileServerURI(targetID, out serverURI); 394 GetUserProfileServerURI(targetID, out serverURI);
333 UUID creatorId = UUID.Zero; 395 if(string.IsNullOrWhiteSpace(serverURI))
334 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>(); 396 {
397 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
398 return;
399 }
335 400
336 OSDMap parameters= new OSDMap(); 401 OSDMap parameters= new OSDMap();
337 UUID.TryParse(args[0], out creatorId); 402
338 parameters.Add("creatorId", OSD.FromUUID(creatorId)); 403 parameters.Add("creatorId", OSD.FromUUID(targetID));
339 OSD Params = (OSD)parameters; 404 OSD Params = (OSD)parameters;
340 if(!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString())) 405 if(!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
341 { 406 {
342 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds); 407 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
343 return; 408 return;
344 } 409 }
345 410
346 parameters = (OSDMap)Params; 411 parameters = (OSDMap)Params;
347 412
348 OSDArray list = (OSDArray)parameters["result"]; 413 if(!parameters.ContainsKey("result") || parameters["result"] == null)
414 {
415 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
416 return;
417 }
349 418
419 OSDArray list = (OSDArray)parameters["result"];
350 420
351 foreach(OSD map in list) 421 foreach(OSD map in list)
352 { 422 {
@@ -360,7 +430,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
360 { 430 {
361 if (!m_classifiedCache.ContainsKey(cid)) 431 if (!m_classifiedCache.ContainsKey(cid))
362 { 432 {
363 m_classifiedCache.Add(cid,creatorId); 433 m_classifiedCache.Add(cid,targetID);
364 m_classifiedInterest.Add(cid, 0); 434 m_classifiedInterest.Add(cid, 0);
365 } 435 }
366 436
@@ -368,11 +438,20 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
368 } 438 }
369 } 439 }
370 440
371 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds); 441 lock(m_profilesCache)
442 {
443 if(!m_profilesCache.TryGetValue(targetID, out uce) || uce == null)
444 uce = new UserProfileCacheEntry();
445 uce.classifiedsLists = classifieds;
446
447 m_profilesCache.AddOrUpdate(targetID, uce, PROFILECACHEEXPIRE);
448 }
449
450 remoteClient.SendAvatarClassifiedReply(targetID, classifieds);
372 } 451 }
373 452
374 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient) 453 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
375 { 454 {
376 UUID target = remoteClient.AgentId; 455 UUID target = remoteClient.AgentId;
377 UserClassifiedAdd ad = new UserClassifiedAdd(); 456 UserClassifiedAdd ad = new UserClassifiedAdd();
378 ad.ClassifiedId = queryClassifiedID; 457 ad.ClassifiedId = queryClassifiedID;
@@ -380,7 +459,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
380 lock (m_classifiedCache) 459 lock (m_classifiedCache)
381 { 460 {
382 if (m_classifiedCache.ContainsKey(queryClassifiedID)) 461 if (m_classifiedCache.ContainsKey(queryClassifiedID))
383 { 462 {
384 target = m_classifiedCache[queryClassifiedID]; 463 target = m_classifiedCache[queryClassifiedID];
385 464
386 m_classifiedInterest[queryClassifiedID] --; 465 m_classifiedInterest[queryClassifiedID] --;
@@ -392,9 +471,33 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
392 } 471 }
393 } 472 }
394 } 473 }
395 474
475 UserProfileCacheEntry uce = null;
476 lock(m_profilesCache)
477 {
478 if(m_profilesCache.TryGetValue(target, out uce) && uce != null)
479 {
480 if(uce.classifieds != null && uce.classifieds.ContainsKey(queryClassifiedID))
481 {
482 ad = uce.classifieds[queryClassifiedID];
483 Vector3 gPos = new Vector3();
484 Vector3.TryParse(ad.GlobalPos, out gPos);
485
486 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate,
487 (uint)ad.ExpirationDate, (uint)ad.Category, ad.Name, ad.Description,
488 ad.ParcelId, (uint)ad.ParentEstate, ad.SnapshotId, ad.SimName,
489 gPos, ad.ParcelName, ad.Flags, ad.Price);
490 return;
491 }
492 }
493 }
494
396 string serverURI = string.Empty; 495 string serverURI = string.Empty;
397 GetUserProfileServerURI(target, out serverURI); 496 bool foreign = GetUserProfileServerURI(target, out serverURI);
497 if(string.IsNullOrWhiteSpace(serverURI))
498 {
499 return;
500 }
398 501
399 object Ad = (object)ad; 502 object Ad = (object)ad;
400 if(!rpc.JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString())) 503 if(!rpc.JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
@@ -408,6 +511,20 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
408 if(ad.CreatorId == UUID.Zero) 511 if(ad.CreatorId == UUID.Zero)
409 return; 512 return;
410 513
514 if(foreign)
515 cacheForeignImage(target, ad.SnapshotId);
516
517 lock(m_profilesCache)
518 {
519 if(!m_profilesCache.TryGetValue(target, out uce) || uce == null)
520 uce = new UserProfileCacheEntry();
521 if(uce.classifieds == null)
522 uce.classifieds = new Dictionary<UUID, UserClassifiedAdd>();
523 uce.classifieds[ad.ClassifiedId] = ad;
524
525 m_profilesCache.AddOrUpdate(target, uce, PROFILECACHEEXPIRE);
526 }
527
411 Vector3 globalPos = new Vector3(); 528 Vector3 globalPos = new Vector3();
412 Vector3.TryParse(ad.GlobalPos, out globalPos); 529 Vector3.TryParse(ad.GlobalPos, out globalPos);
413 530
@@ -458,36 +575,62 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
458 int queryclassifiedPrice, IClientAPI remoteClient) 575 int queryclassifiedPrice, IClientAPI remoteClient)
459 { 576 {
460 Scene s = (Scene)remoteClient.Scene; 577 Scene s = (Scene)remoteClient.Scene;
461 IMoneyModule money = s.RequestModuleInterface<IMoneyModule>(); 578 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
579 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
580 UUID creatorId = remoteClient.AgentId;
581 ScenePresence p = FindPresence(creatorId);
462 582
463 if (money != null) 583 UserProfileCacheEntry uce = null;
584 lock(m_profilesCache)
585 m_profilesCache.TryGetValue(remoteClient.AgentId, out uce);
586
587 string serverURI = string.Empty;
588 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
589 if(string.IsNullOrWhiteSpace(serverURI))
464 { 590 {
465 if (!money.AmountCovered(remoteClient.AgentId, queryclassifiedPrice)) 591 return;
466 {
467 remoteClient.SendAgentAlertMessage("You do not have enough money to create requested classified.", false);
468 return;
469 }
470 money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge);
471 } 592 }
472 593
473 UserClassifiedAdd ad = new UserClassifiedAdd(); 594 if(foreign)
474 595 {
475 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition; 596 remoteClient.SendAgentAlertMessage("Please change classifieds on your home grid", true);
476 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y); 597 if(uce != null && uce.classifiedsLists != null)
477 ScenePresence p = FindPresence(remoteClient.AgentId); 598 remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists);
478 599 return;
479 string serverURI = string.Empty; 600 }
480 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
481 601
482 if (land == null) 602 OSDMap parameters = new OSDMap {{"creatorId", OSD.FromUUID(creatorId)}};
603 OSD Params = (OSD)parameters;
604 if (!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
483 { 605 {
484 ad.ParcelName = string.Empty; 606 remoteClient.SendAgentAlertMessage("Error fetching classifieds", false);
607 return;
485 } 608 }
486 else 609 parameters = (OSDMap)Params;
610 OSDArray list = (OSDArray)parameters["result"];
611 bool exists = list.Cast<OSDMap>().Where(map => map.ContainsKey("classifieduuid"))
612 .Any(map => map["classifieduuid"].AsUUID().Equals(queryclassifiedID));
613
614 IMoneyModule money = null;
615 if (!exists)
487 { 616 {
488 ad.ParcelName = land.LandData.Name; 617 money = s.RequestModuleInterface<IMoneyModule>();
618 if (money != null)
619 {
620 if (!money.AmountCovered(remoteClient.AgentId, queryclassifiedPrice))
621 {
622 remoteClient.SendAgentAlertMessage("You do not have enough money to create this classified.", false);
623 if(uce != null && uce.classifiedsLists != null)
624 remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists);
625 return;
626 }
627// money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge);
628 }
489 } 629 }
490 630
631 UserClassifiedAdd ad = new UserClassifiedAdd();
632
633 ad.ParcelName = land == null ? string.Empty : land.LandData.Name;
491 ad.CreatorId = remoteClient.AgentId; 634 ad.CreatorId = remoteClient.AgentId;
492 ad.ClassifiedId = queryclassifiedID; 635 ad.ClassifiedId = queryclassifiedID;
493 ad.Category = Convert.ToInt32(queryCategory); 636 ad.Category = Convert.ToInt32(queryCategory);
@@ -507,10 +650,26 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
507 650
508 if(!rpc.JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString())) 651 if(!rpc.JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
509 { 652 {
510 remoteClient.SendAgentAlertMessage( 653 remoteClient.SendAgentAlertMessage("Error updating classified", false);
511 "Error updating classified", false); 654 if(uce != null && uce.classifiedsLists != null)
655 remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists);
512 return; 656 return;
513 } 657 }
658
659 // only charge if it worked
660 if (money != null)
661 money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge);
662
663 // just flush cache for now
664 lock(m_profilesCache)
665 {
666 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
667 {
668 uce.classifieds = null;
669 uce.classifiedsLists = null;
670 }
671 }
672
514 } 673 }
515 674
516 /// <summary> 675 /// <summary>
@@ -524,12 +683,23 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
524 /// </param> 683 /// </param>
525 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient) 684 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
526 { 685 {
686
527 string serverURI = string.Empty; 687 string serverURI = string.Empty;
528 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 688 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
689 if(string.IsNullOrWhiteSpace(serverURI))
690 return;
691
692 if(foreign)
693 {
694 remoteClient.SendAgentAlertMessage("Please change classifieds on your home grid", true);
695 return;
696 }
529 697
530 UUID classifiedId; 698 UUID classifiedId;
699 if(!UUID.TryParse(queryClassifiedID.ToString(), out classifiedId))
700 return;
701
531 OSDMap parameters= new OSDMap(); 702 OSDMap parameters= new OSDMap();
532 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
533 parameters.Add("classifiedId", OSD.FromUUID(classifiedId)); 703 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
534 OSD Params = (OSD)parameters; 704 OSD Params = (OSD)parameters;
535 if(!rpc.JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString())) 705 if(!rpc.JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
@@ -539,6 +709,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
539 return; 709 return;
540 } 710 }
541 711
712 // flush cache
713 UserProfileCacheEntry uce = null;
714 lock(m_profilesCache)
715 {
716 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
717 {
718 uce.classifieds = null;
719 uce.classifiedsLists = null;
720 }
721 }
722
542 parameters = (OSDMap)Params; 723 parameters = (OSDMap)Params;
543 } 724 }
544 #endregion Classified 725 #endregion Classified
@@ -564,33 +745,54 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
564 IClientAPI remoteClient = (IClientAPI)sender; 745 IClientAPI remoteClient = (IClientAPI)sender;
565 746
566 UUID targetId; 747 UUID targetId;
567 UUID.TryParse(args[0], out targetId); 748 if(!UUID.TryParse(args[0], out targetId))
749 return;
750
751 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
568 752
569 // Can't handle NPC yet...
570 ScenePresence p = FindPresence(targetId); 753 ScenePresence p = FindPresence(targetId);
754 if (p != null && p.IsNPC)
755 {
756 remoteClient.SendAvatarPicksReply(targetId, picks);
757 return;
758 }
571 759
572 if (null != p) 760 UserProfileCacheEntry uce = null;
761 lock(m_profilesCache)
573 { 762 {
574 if (p.PresenceType == PresenceType.Npc) 763 if(m_profilesCache.TryGetValue(targetId, out uce) && uce != null)
575 return; 764 {
765 if(uce != null && uce.picksList != null)
766 {
767 remoteClient.SendAvatarPicksReply(targetId, uce.picksList);
768 return;
769 }
770 }
576 } 771 }
577 772
578 string serverURI = string.Empty; 773 string serverURI = string.Empty;
579 GetUserProfileServerURI(targetId, out serverURI); 774 GetUserProfileServerURI(targetId, out serverURI);
580 775 if(string.IsNullOrWhiteSpace(serverURI))
581 Dictionary<UUID, string> picks = new Dictionary<UUID, string>(); 776 {
777 remoteClient.SendAvatarPicksReply(targetId, picks);
778 return;
779 }
582 780
583 OSDMap parameters= new OSDMap(); 781 OSDMap parameters= new OSDMap();
584 parameters.Add("creatorId", OSD.FromUUID(targetId)); 782 parameters.Add("creatorId", OSD.FromUUID(targetId));
585 OSD Params = (OSD)parameters; 783 OSD Params = (OSD)parameters;
586 if(!rpc.JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString())) 784 if(!rpc.JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
587 { 785 {
588 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks); 786 remoteClient.SendAvatarPicksReply(targetId, picks);
589 return; 787 return;
590 } 788 }
591 789
592 parameters = (OSDMap)Params; 790 parameters = (OSDMap)Params;
593 791 if(!parameters.ContainsKey("result") || parameters["result"] == null)
792 {
793 remoteClient.SendAvatarPicksReply(targetId, picks);
794 return;
795 }
594 OSDArray list = (OSDArray)parameters["result"]; 796 OSDArray list = (OSDArray)parameters["result"];
595 797
596 foreach(OSD map in list) 798 foreach(OSD map in list)
@@ -598,12 +800,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
598 OSDMap m = (OSDMap)map; 800 OSDMap m = (OSDMap)map;
599 UUID cid = m["pickuuid"].AsUUID(); 801 UUID cid = m["pickuuid"].AsUUID();
600 string name = m["name"].AsString(); 802 string name = m["name"].AsString();
601
602 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
603
604 picks[cid] = name; 803 picks[cid] = name;
605 } 804 }
606 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks); 805
806 lock(m_profilesCache)
807 {
808 if(!m_profilesCache.TryGetValue(targetId, out uce) || uce == null)
809 uce = new UserProfileCacheEntry();
810 uce.picksList = picks;
811
812 m_profilesCache.AddOrUpdate(targetId, uce, PROFILECACHEEXPIRE);
813 }
814
815 remoteClient.SendAvatarPicksReply(targetId, picks);
607 } 816 }
608 817
609 /// <summary> 818 /// <summary>
@@ -623,21 +832,45 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
623 if (!(sender is IClientAPI)) 832 if (!(sender is IClientAPI))
624 return; 833 return;
625 834
835 UserProfilePick pick = new UserProfilePick ();
626 UUID targetID; 836 UUID targetID;
627 UUID.TryParse (args [0], out targetID); 837 if(!UUID.TryParse(args [0], out targetID))
628 string serverURI = string.Empty; 838 return;
629 GetUserProfileServerURI (targetID, out serverURI);
630 839
631 string theirGatekeeperURI; 840 pick.CreatorId = targetID;
632 GetUserGatekeeperURI (targetID, out theirGatekeeperURI); 841
842 if(!UUID.TryParse (args [1], out pick.PickId))
843 return;
633 844
634 IClientAPI remoteClient = (IClientAPI)sender; 845 IClientAPI remoteClient = (IClientAPI)sender;
846 UserProfileCacheEntry uce = null;
847 lock(m_profilesCache)
848 {
849 if(m_profilesCache.TryGetValue(targetID, out uce) && uce != null)
850 {
851 if(uce != null && uce.picks != null && uce.picks.ContainsKey(pick.PickId))
852 {
853 pick = uce.picks[pick.PickId];
854 Vector3 gPos = new Vector3(Vector3.Zero);
855 Vector3.TryParse(pick.GlobalPos, out gPos);
856 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
857 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName,
858 gPos,pick.SortOrder,pick.Enabled);
859 return;
860 }
861 }
862 }
635 863
636 UserProfilePick pick = new UserProfilePick (); 864 string serverURI = string.Empty;
637 UUID.TryParse (args [0], out pick.CreatorId); 865 bool foreign = GetUserProfileServerURI (targetID, out serverURI);
638 UUID.TryParse (args [1], out pick.PickId); 866 if(string.IsNullOrWhiteSpace(serverURI))
867 {
868 return;
869 }
870
871 string theirGatekeeperURI;
872 GetUserGatekeeperURI(targetID, out theirGatekeeperURI);
639 873
640
641 object Pick = (object)pick; 874 object Pick = (object)pick;
642 if (!rpc.JsonRpcRequest (ref Pick, "pickinforequest", serverURI, UUID.Random ().ToString ())) { 875 if (!rpc.JsonRpcRequest (ref Pick, "pickinforequest", serverURI, UUID.Random ().ToString ())) {
643 remoteClient.SendAgentAlertMessage ( 876 remoteClient.SendAgentAlertMessage (
@@ -645,15 +878,13 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
645 return; 878 return;
646 } 879 }
647 pick = (UserProfilePick)Pick; 880 pick = (UserProfilePick)Pick;
648 881 if(foreign)
882 cacheForeignImage(targetID, pick.SnapshotId);
883
649 Vector3 globalPos = new Vector3(Vector3.Zero); 884 Vector3 globalPos = new Vector3(Vector3.Zero);
650 885 Vector3.TryParse(pick.GlobalPos, out globalPos);
651 // Smoke and mirrors 886
652 if (pick.Gatekeeper == MyGatekeeper) 887 if (!string.IsNullOrWhiteSpace(MyGatekeeper) && pick.Gatekeeper != MyGatekeeper)
653 {
654 Vector3.TryParse(pick.GlobalPos,out globalPos);
655 }
656 else
657 { 888 {
658 // Setup the illusion 889 // Setup the illusion
659 string region = string.Format("{0} {1}",pick.Gatekeeper,pick.SimName); 890 string region = string.Format("{0} {1}",pick.Gatekeeper,pick.SimName);
@@ -661,26 +892,52 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
661 892
662 if(target == null) 893 if(target == null)
663 { 894 {
664 // This is a dead or unreachable region 895 // This is a unreachable region
665 } 896 }
666 else 897 else
667 { 898 {
668 // Work our slight of hand 899 // we have a proxy on map
669 int x = target.RegionLocX; 900 ulong oriHandle;
670 int y = target.RegionLocY; 901 uint oriX;
902 uint oriY;
903 if(Util.ParseFakeParcelID(pick.ParcelId, out oriHandle, out oriX, out oriY))
904 {
905 pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, oriX, oriY);
906 globalPos.X = target.RegionLocX + oriX;
907 globalPos.Y = target.RegionLocY + oriY;
908 pick.GlobalPos = globalPos.ToString();
909 }
910 else
911 {
912 // this is a fail on large regions
913 uint gtmp = (uint)globalPos.X >> 8;
914 globalPos.X -= (gtmp << 8);
915
916 gtmp = (uint)globalPos.Y >> 8;
917 globalPos.Y -= (gtmp << 8);
671 918
672 dynamic synthX = globalPos.X - (globalPos.X/Constants.RegionSize) * Constants.RegionSize; 919 pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, (uint)globalPos.X, (uint)globalPos.Y);
673 synthX += x;
674 globalPos.X = synthX;
675 920
676 dynamic synthY = globalPos.Y - (globalPos.Y/Constants.RegionSize) * Constants.RegionSize; 921 globalPos.X += target.RegionLocX;
677 synthY += y; 922 globalPos.Y += target.RegionLocY;
678 globalPos.Y = synthY; 923 pick.GlobalPos = globalPos.ToString();
924 }
679 } 925 }
680 } 926 }
681 927
682 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString()); 928 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
683 929
930 lock(m_profilesCache)
931 {
932 if(!m_profilesCache.TryGetValue(targetID, out uce) || uce == null)
933 uce = new UserProfileCacheEntry();
934 if(uce.picks == null)
935 uce.picks = new Dictionary<UUID, UserProfilePick>();
936 uce.picks[pick.PickId] = pick;
937
938 m_profilesCache.AddOrUpdate(targetID, uce, PROFILECACHEEXPIRE);
939 }
940
684 // Pull the rabbit out of the hat 941 // Pull the rabbit out of the hat
685 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name, 942 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
686 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName, 943 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName,
@@ -718,13 +975,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
718 /// Enabled. 975 /// Enabled.
719 /// </param> 976 /// </param>
720 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled) 977 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
721 { 978 {
722 //TODO: See how this works with NPC, May need to test
723 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString()); 979 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
724 980
725 UserProfilePick pick = new UserProfilePick(); 981 UserProfilePick pick = new UserProfilePick();
726 string serverURI = string.Empty; 982 string serverURI = string.Empty;
727 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 983 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
984 if(string.IsNullOrWhiteSpace(serverURI))
985 {
986 return;
987 }
988
728 ScenePresence p = FindPresence(remoteClient.AgentId); 989 ScenePresence p = FindPresence(remoteClient.AgentId);
729 990
730 Vector3 avaPos = p.AbsolutePosition; 991 Vector3 avaPos = p.AbsolutePosition;
@@ -734,24 +995,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
734 avaPos.Z); 995 avaPos.Z);
735 996
736 string landParcelName = "My Parcel"; 997 string landParcelName = "My Parcel";
737 UUID landParcelID = p.currentParcelUUID; 998// UUID landParcelID = p.currentParcelUUID;
738 999
1000 // to locate parcels we use a fake id that encodes the region handle
1001 // since we do not have a global locator
1002 // this fails on HG
1003 UUID landParcelID = Util.BuildFakeParcelID(remoteClient.Scene.RegionInfo.RegionHandle, (uint)avaPos.X, (uint)avaPos.Y);
739 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y); 1004 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
740 1005
741 if (land != null) 1006 if (land != null)
742 { 1007 {
743 // If land found, use parcel uuid from here because the value from SP will be blank if the avatar hasnt moved 1008 // If land found, use parcel uuid from here because the value from SP will be blank if the avatar hasnt moved
744 landParcelName = land.LandData.Name; 1009 landParcelName = land.LandData.Name;
745 landParcelID = land.LandData.GlobalID; 1010// landParcelID = land.LandData.GlobalID;
746 } 1011 }
747 else 1012 else
748 { 1013 {
749 m_log.WarnFormat( 1014 m_log.WarnFormat(
750 "[PROFILES]: PickInfoUpdate found no parcel info at {0},{1} in {2}", 1015 "[PROFILES]: PickInfoUpdate found no parcel info at {0},{1} in {2}",
751 avaPos.X, avaPos.Y, p.Scene.Name); 1016 avaPos.X, avaPos.Y, p.Scene.Name);
752 } 1017 }
753 1018
754
755 pick.PickId = pickID; 1019 pick.PickId = pickID;
756 pick.CreatorId = creatorID; 1020 pick.CreatorId = creatorID;
757 pick.TopPick = topPick; 1021 pick.TopPick = topPick;
@@ -774,6 +1038,24 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
774 return; 1038 return;
775 } 1039 }
776 1040
1041 UserProfileCacheEntry uce = null;
1042 lock(m_profilesCache)
1043 {
1044 if(!m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) || uce == null)
1045 uce = new UserProfileCacheEntry();
1046 if(uce.picks == null)
1047 uce.picks = new Dictionary<UUID, UserProfilePick>();
1048 if(uce.picksList == null)
1049 uce.picksList = new Dictionary<UUID, string>();
1050 uce.picks[pick.PickId] = pick;
1051 uce.picksList[pick.PickId] = pick.Name;
1052 m_profilesCache.AddOrUpdate(remoteClient.AgentId, uce, PROFILECACHEEXPIRE);
1053 }
1054 remoteClient.SendAvatarPicksReply(remoteClient.AgentId, uce.picksList);
1055 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
1056 pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName,
1057 posGlobal,pick.SortOrder,pick.Enabled);
1058
777 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString()); 1059 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
778 } 1060 }
779 1061
@@ -790,6 +1072,10 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
790 { 1072 {
791 string serverURI = string.Empty; 1073 string serverURI = string.Empty;
792 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1074 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1075 if(string.IsNullOrWhiteSpace(serverURI))
1076 {
1077 return;
1078 }
793 1079
794 OSDMap parameters= new OSDMap(); 1080 OSDMap parameters= new OSDMap();
795 parameters.Add("pickId", OSD.FromUUID(queryPickID)); 1081 parameters.Add("pickId", OSD.FromUUID(queryPickID));
@@ -800,6 +1086,23 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
800 "Error picks delete", false); 1086 "Error picks delete", false);
801 return; 1087 return;
802 } 1088 }
1089
1090 UserProfileCacheEntry uce = null;
1091 lock(m_profilesCache)
1092 {
1093 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
1094 {
1095 if(uce.picks != null && uce.picks.ContainsKey(queryPickID))
1096 uce.picks.Remove(queryPickID);
1097 if(uce.picksList != null && uce.picksList.ContainsKey(queryPickID))
1098 uce.picksList.Remove(queryPickID);
1099 m_profilesCache.AddOrUpdate(remoteClient.AgentId, uce, PROFILECACHEEXPIRE);
1100 }
1101 }
1102 if(uce != null && uce.picksList != null)
1103 remoteClient.SendAvatarPicksReply(remoteClient.AgentId, uce.picksList);
1104 else
1105 remoteClient.SendAvatarPicksReply(remoteClient.AgentId, new Dictionary<UUID, string>());
803 } 1106 }
804 #endregion Picks 1107 #endregion Picks
805 1108
@@ -823,11 +1126,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
823 if (!(sender is IClientAPI)) 1126 if (!(sender is IClientAPI))
824 return; 1127 return;
825 1128
1129 if(!UUID.TryParse(args[0], out note.TargetId))
1130 return;
1131
826 IClientAPI remoteClient = (IClientAPI)sender; 1132 IClientAPI remoteClient = (IClientAPI)sender;
1133 note.UserId = remoteClient.AgentId;
1134
827 string serverURI = string.Empty; 1135 string serverURI = string.Empty;
828 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1136 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
829 note.UserId = remoteClient.AgentId; 1137 if(string.IsNullOrWhiteSpace(serverURI))
830 UUID.TryParse(args[0], out note.TargetId); 1138 {
1139 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
1140 return;
1141 }
831 1142
832 object Note = (object)note; 1143 object Note = (object)note;
833 if(!rpc.JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString())) 1144 if(!rpc.JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
@@ -836,7 +1147,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
836 return; 1147 return;
837 } 1148 }
838 note = (UserProfileNotes) Note; 1149 note = (UserProfileNotes) Note;
839
840 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes); 1150 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
841 } 1151 }
842 1152
@@ -854,6 +1164,14 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
854 /// </param> 1164 /// </param>
855 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes) 1165 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
856 { 1166 {
1167 ScenePresence p = FindPresence(queryTargetID);
1168 if (p != null && p.IsNPC)
1169 {
1170 remoteClient.SendAgentAlertMessage(
1171 "Notes for NPCs not available", false);
1172 return;
1173 }
1174
857 UserProfileNotes note = new UserProfileNotes(); 1175 UserProfileNotes note = new UserProfileNotes();
858 1176
859 note.UserId = remoteClient.AgentId; 1177 note.UserId = remoteClient.AgentId;
@@ -862,6 +1180,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
862 1180
863 string serverURI = string.Empty; 1181 string serverURI = string.Empty;
864 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1182 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1183 if(string.IsNullOrWhiteSpace(serverURI))
1184 return;
865 1185
866 object Note = note; 1186 object Note = note;
867 if(!rpc.JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString())) 1187 if(!rpc.JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
@@ -873,6 +1193,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
873 } 1193 }
874 #endregion Notes 1194 #endregion Notes
875 1195
1196
876 #region User Preferences 1197 #region User Preferences
877 /// <summary> 1198 /// <summary>
878 /// Updates the user preferences. 1199 /// Updates the user preferences.
@@ -896,16 +1217,18 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
896 1217
897 string serverURI = string.Empty; 1218 string serverURI = string.Empty;
898 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1219 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1220 if(string.IsNullOrWhiteSpace(serverURI))
1221 return;
899 1222
900 object Pref = pref; 1223 object Pref = pref;
901 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_update", serverURI, UUID.Random().ToString())) 1224 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_update", serverURI, UUID.Random().ToString()))
902 { 1225 {
903 m_log.InfoFormat("[PROFILES]: UserPreferences update error"); 1226 m_log.InfoFormat("[PROFILES]: UserPreferences update error");
904 remoteClient.SendAgentAlertMessage("Error updating preferences", false); 1227 remoteClient.SendAgentAlertMessage("Error updating preferences", false);
905 return; 1228 return;
906 } 1229 }
907 } 1230 }
908 1231
909 /// <summary> 1232 /// <summary>
910 /// Users the preferences request. 1233 /// Users the preferences request.
911 /// </summary> 1234 /// </summary>
@@ -920,7 +1243,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
920 1243
921 string serverURI = string.Empty; 1244 string serverURI = string.Empty;
922 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1245 bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
923 1246 if(string.IsNullOrWhiteSpace(serverURI))
1247 return;
924 1248
925 object Pref = (object)pref; 1249 object Pref = (object)pref;
926 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_request", serverURI, UUID.Random().ToString())) 1250 if(!rpc.JsonRpcRequest(ref Pref, "user_preferences_request", serverURI, UUID.Random().ToString()))
@@ -932,7 +1256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
932 pref = (UserPreferences) Pref; 1256 pref = (UserPreferences) Pref;
933 1257
934 remoteClient.SendUserInfoReply(pref.IMViaEmail, pref.Visible, pref.EMail); 1258 remoteClient.SendUserInfoReply(pref.IMViaEmail, pref.Visible, pref.EMail);
935 1259
936 } 1260 }
937 #endregion User Preferences 1261 #endregion User Preferences
938 1262
@@ -960,6 +1284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
960 /// </param> 1284 /// </param>
961 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages) 1285 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
962 { 1286 {
1287
963 UserProfileProperties prop = new UserProfileProperties(); 1288 UserProfileProperties prop = new UserProfileProperties();
964 1289
965 prop.UserId = remoteClient.AgentId; 1290 prop.UserId = remoteClient.AgentId;
@@ -971,6 +1296,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
971 1296
972 string serverURI = string.Empty; 1297 string serverURI = string.Empty;
973 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1298 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1299 if(string.IsNullOrWhiteSpace(serverURI))
1300 return;
974 1301
975 object Param = prop; 1302 object Param = prop;
976 if(!rpc.JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString())) 1303 if(!rpc.JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
@@ -979,6 +1306,17 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
979 "Error updating interests", false); 1306 "Error updating interests", false);
980 return; 1307 return;
981 } 1308 }
1309
1310 // flush cache
1311 UserProfileCacheEntry uce = null;
1312 lock(m_profilesCache)
1313 {
1314 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
1315 {
1316 uce.props = null;
1317 }
1318 }
1319
982 } 1320 }
983 1321
984 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) 1322 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
@@ -990,13 +1328,55 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
990 return; 1328 return;
991 } 1329 }
992 1330
993 // Can't handle NPC yet...
994 ScenePresence p = FindPresence(avatarID); 1331 ScenePresence p = FindPresence(avatarID);
995 1332 if (p != null && p.IsNPC)
996 if (null != p)
997 { 1333 {
998 if (p.PresenceType == PresenceType.Npc) 1334 remoteClient.SendAvatarProperties(avatarID, ((INPC)(p.ControllingClient)).profileAbout, ((INPC)(p.ControllingClient)).Born,
999 return; 1335 Utils.StringToBytes("Non Player Character (NPC)"), "NPCs have no life", 0x10,
1336 UUID.Zero, ((INPC)(p.ControllingClient)).profileImage, "", UUID.Zero);
1337 remoteClient.SendAvatarInterestsReply(avatarID, 0, "",
1338 0, "Getting into trouble", "Droidspeak");
1339 return;
1340 }
1341 UserProfileProperties props;
1342 UserProfileCacheEntry uce = null;
1343 lock(m_profilesCache)
1344 {
1345 if(m_profilesCache.TryGetValue(avatarID, out uce) && uce != null)
1346 {
1347 if(uce.props != null)
1348 {
1349 props = uce.props;
1350 uint cflags = uce.flags;
1351 // if on same region force online
1352 if(p != null && !p.IsDeleted)
1353 cflags |= 0x10;
1354
1355 remoteClient.SendAvatarProperties(props.UserId, props.AboutText,
1356 uce.born, uce.membershipType , props.FirstLifeText, cflags,
1357 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
1358
1359 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask,
1360 props.WantToText, (uint)props.SkillsMask,
1361 props.SkillsText, props.Language);
1362 return;
1363 }
1364 else
1365 {
1366 if(uce.ClientsWaitingProps == null)
1367 uce.ClientsWaitingProps = new HashSet<IClientAPI>();
1368 else if(uce.ClientsWaitingProps.Contains(remoteClient))
1369 return;
1370 uce.ClientsWaitingProps.Add(remoteClient);
1371 }
1372 }
1373 else
1374 {
1375 uce = new UserProfileCacheEntry();
1376 uce.ClientsWaitingProps = new HashSet<IClientAPI>();
1377 uce.ClientsWaitingProps.Add(remoteClient);
1378 m_profilesCache.AddOrUpdate(avatarID, uce, PROFILECACHEEXPIRE);
1379 }
1000 } 1380 }
1001 1381
1002 string serverURI = string.Empty; 1382 string serverURI = string.Empty;
@@ -1014,20 +1394,16 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1014 userInfo = new Dictionary<string, object>(); 1394 userInfo = new Dictionary<string, object>();
1015 } 1395 }
1016 1396
1017 Byte[] charterMember = new Byte[1]; 1397 Byte[] membershipType = new Byte[1];
1018 string born = String.Empty; 1398 string born = string.Empty;
1019 uint flags = 0x00; 1399 uint flags = 0x00;
1020 1400
1021 if (null != account) 1401 if (null != account)
1022 { 1402 {
1023 if (account.UserTitle == "") 1403 if (account.UserTitle == "")
1024 { 1404 membershipType[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
1025 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
1026 }
1027 else 1405 else
1028 { 1406 membershipType = Utils.StringToBytes(account.UserTitle);
1029 charterMember = Utils.StringToBytes(account.UserTitle);
1030 }
1031 1407
1032 born = Util.ToDateTime(account.Created).ToString( 1408 born = Util.ToDateTime(account.Created).ToString(
1033 "M/d/yyyy", CultureInfo.InvariantCulture); 1409 "M/d/yyyy", CultureInfo.InvariantCulture);
@@ -1038,16 +1414,13 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1038 if (GetUserAccountData(avatarID, out userInfo) == true) 1414 if (GetUserAccountData(avatarID, out userInfo) == true)
1039 { 1415 {
1040 if ((string)userInfo["user_title"] == "") 1416 if ((string)userInfo["user_title"] == "")
1041 { 1417 membershipType[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
1042 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
1043 }
1044 else 1418 else
1045 { 1419 membershipType = Utils.StringToBytes((string)userInfo["user_title"]);
1046 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
1047 }
1048 1420
1049 int val_born = (int)userInfo["user_created"]; 1421 int val_born = (int)userInfo["user_created"];
1050 born = Util.ToDateTime(val_born).ToString( 1422 if(val_born != 0)
1423 born = Util.ToDateTime(val_born).ToString(
1051 "M/d/yyyy", CultureInfo.InvariantCulture); 1424 "M/d/yyyy", CultureInfo.InvariantCulture);
1052 1425
1053 // picky, picky 1426 // picky, picky
@@ -1056,23 +1429,60 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1056 } 1429 }
1057 } 1430 }
1058 1431
1059 UserProfileProperties props = new UserProfileProperties(); 1432 props = new UserProfileProperties();
1433 props.UserId = avatarID;
1434
1060 string result = string.Empty; 1435 string result = string.Empty;
1436 if(!GetProfileData(ref props, foreign, serverURI, out result))
1437 {
1438 props.AboutText ="Profile not available at this time. User may still be unknown to this grid";
1439 }
1061 1440
1062 props.UserId = avatarID; 1441 if(!m_allowUserProfileWebURLs)
1442 props.WebUrl ="";
1063 1443
1064 if (!GetProfileData(ref props, foreign, out result)) 1444 HashSet<IClientAPI> clients;
1445 lock(m_profilesCache)
1065 { 1446 {
1066// m_log.DebugFormat("Error getting profile for {0}: {1}", avatarID, result); 1447 if(!m_profilesCache.TryGetValue(props.UserId, out uce) || uce == null)
1067 return; 1448 uce = new UserProfileCacheEntry();
1449 uce.props = props;
1450 uce.born = born;
1451 uce.membershipType = membershipType;
1452 uce.flags = flags;
1453 clients = uce.ClientsWaitingProps;
1454 uce.ClientsWaitingProps = null;
1455 m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE);
1068 } 1456 }
1069 1457
1070 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags, 1458 // if on same region force online
1459 if(p != null && !p.IsDeleted)
1460 flags |= 0x10;
1461
1462 if(clients == null)
1463 {
1464 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
1071 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); 1465 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
1072 1466
1467 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
1468 (uint)props.SkillsMask, props.SkillsText, props.Language);
1469 }
1470 else
1471 {
1472 if(!clients.Contains(remoteClient))
1473 clients.Add(remoteClient);
1474 foreach(IClientAPI cli in clients)
1475 {
1476 if(!cli.IsActive)
1477 continue;
1478 cli.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
1479 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
1480
1481 cli.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
1482 (uint)props.SkillsMask, props.SkillsText, props.Language);
1073 1483
1074 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask, 1484 }
1075 props.SkillsText, props.Language); 1485 }
1076 } 1486 }
1077 1487
1078 /// <summary> 1488 /// <summary>
@@ -1088,6 +1498,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1088 { 1498 {
1089 if (remoteClient.AgentId == newProfile.ID) 1499 if (remoteClient.AgentId == newProfile.ID)
1090 { 1500 {
1501
1091 UserProfileProperties prop = new UserProfileProperties(); 1502 UserProfileProperties prop = new UserProfileProperties();
1092 1503
1093 prop.UserId = remoteClient.AgentId; 1504 prop.UserId = remoteClient.AgentId;
@@ -1097,6 +1508,9 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1097 prop.FirstLifeImageId = newProfile.FirstLifeImage; 1508 prop.FirstLifeImageId = newProfile.FirstLifeImage;
1098 prop.FirstLifeText = newProfile.FirstLifeAboutText; 1509 prop.FirstLifeText = newProfile.FirstLifeAboutText;
1099 1510
1511 if(!m_allowUserProfileWebURLs)
1512 prop.WebUrl ="";
1513
1100 string serverURI = string.Empty; 1514 string serverURI = string.Empty;
1101 GetUserProfileServerURI(remoteClient.AgentId, out serverURI); 1515 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
1102 1516
@@ -1109,6 +1523,16 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1109 return; 1523 return;
1110 } 1524 }
1111 1525
1526 // flush cache
1527 UserProfileCacheEntry uce = null;
1528 lock(m_profilesCache)
1529 {
1530 if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null)
1531 {
1532 uce.props = null;
1533 }
1534 }
1535
1112 RequestAvatarProperties(remoteClient, newProfile.ID); 1536 RequestAvatarProperties(remoteClient, newProfile.ID);
1113 } 1537 }
1114 } 1538 }
@@ -1119,28 +1543,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1119 /// <returns> 1543 /// <returns>
1120 /// The profile data. 1544 /// The profile data.
1121 /// </returns> 1545 /// </returns>
1122 bool GetProfileData(ref UserProfileProperties properties, bool foreign, out string message) 1546 bool GetProfileData(ref UserProfileProperties properties, bool foreign, string serverURI, out string message)
1123 { 1547 {
1124 // Can't handle NPC yet...
1125 ScenePresence p = FindPresence(properties.UserId);
1126
1127 if (null != p)
1128 {
1129 if (p.PresenceType == PresenceType.Npc)
1130 {
1131 message = "Id points to NPC";
1132 return false;
1133 }
1134 }
1135
1136 string serverURI = string.Empty;
1137 GetUserProfileServerURI(properties.UserId, out serverURI);
1138
1139 // This is checking a friend on the home grid
1140 // Not HG friend
1141 if (String.IsNullOrEmpty(serverURI)) 1548 if (String.IsNullOrEmpty(serverURI))
1142 { 1549 {
1143 message = "No Presence - foreign friend"; 1550 message = "User profile service unknown at this time";
1144 return false; 1551 return false;
1145 } 1552 }
1146 1553
@@ -1161,7 +1568,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1161 { 1568 {
1162 m_log.Debug( 1569 m_log.Debug(
1163 string.Format( 1570 string.Format(
1164 "[PROFILES]: Request using the OpenProfile API for user {0} to {1} failed", 1571 "[PROFILES]: Request using the OpenProfile API for user {0} to {1} failed",
1165 properties.UserId, serverURI), 1572 properties.UserId, serverURI),
1166 e); 1573 e);
1167 1574
@@ -1178,10 +1585,14 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1178 1585
1179 return false; 1586 return false;
1180 } 1587 }
1181 // else, continue below
1182 } 1588 }
1183 1589
1184 properties = (UserProfileProperties)Prop; 1590 properties = (UserProfileProperties)Prop;
1591 if(foreign)
1592 {
1593 cacheForeignImage(properties.UserId, properties.ImageId);
1594 cacheForeignImage(properties.UserId, properties.FirstLifeImageId);
1595 }
1185 1596
1186 message = "Success"; 1597 message = "Success";
1187 return true; 1598 return true;
@@ -1189,49 +1600,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1189 #endregion Avatar Properties 1600 #endregion Avatar Properties
1190 1601
1191 #region Utils 1602 #region Utils
1192 bool GetImageAssets(UUID avatarId)
1193 {
1194 string profileServerURI = string.Empty;
1195 string assetServerURI = string.Empty;
1196
1197 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1198
1199 if(!foreign)
1200 return true;
1201
1202 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1203
1204 if(string.IsNullOrEmpty(profileServerURI) || string.IsNullOrEmpty(assetServerURI))
1205 return false;
1206
1207 OSDMap parameters= new OSDMap();
1208 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1209 OSD Params = (OSD)parameters;
1210 if(!rpc.JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1211 {
1212 return false;
1213 }
1214
1215 parameters = (OSDMap)Params;
1216
1217 if (parameters.ContainsKey("result"))
1218 {
1219 OSDArray list = (OSDArray)parameters["result"];
1220
1221 foreach (OSD asset in list)
1222 {
1223 OSDString assetId = (OSDString)asset;
1224
1225 Scene.AssetService.Get(string.Format("{0}/{1}", assetServerURI, assetId.AsString()));
1226 }
1227 return true;
1228 }
1229 else
1230 {
1231 m_log.ErrorFormat("[PROFILES]: Problematic response for image_assets_request from {0}", profileServerURI);
1232 return false;
1233 }
1234 }
1235 1603
1236 /// <summary> 1604 /// <summary>
1237 /// Gets the user account data. 1605 /// Gets the user account data.
@@ -1336,7 +1704,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1336 { 1704 {
1337 bool local; 1705 bool local;
1338 local = UserManagementModule.IsLocalGridUser(userID); 1706 local = UserManagementModule.IsLocalGridUser(userID);
1339 1707
1340 if (!local) 1708 if (!local)
1341 { 1709 {
1342 serverURI = UserManagementModule.GetUserServerURL(userID, "GatekeeperURI"); 1710 serverURI = UserManagementModule.GetUserServerURL(userID, "GatekeeperURI");
@@ -1382,6 +1750,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1382 } 1750 }
1383 } 1751 }
1384 1752
1753 void cacheForeignImage(UUID agent, UUID imageID)
1754 {
1755 if(imageID == null || imageID == UUID.Zero)
1756 return;
1757
1758 string assetServerURI = UserManagementModule.GetUserServerURL(agent, "AssetServerURI");
1759 if(string.IsNullOrWhiteSpace(assetServerURI))
1760 return;
1761
1762 string imageIDstr = imageID.ToString();
1763
1764
1765 if(m_assetCache != null && m_assetCache.Check(imageIDstr))
1766 return;
1767
1768 if(Scene.AssetService.Get(imageIDstr) != null)
1769 return;
1770
1771 Scene.AssetService.Get(string.Format("{0}/{1}", assetServerURI, imageIDstr));
1772 }
1773
1385 /// <summary> 1774 /// <summary>
1386 /// Finds the presence. 1775 /// Finds the presence.
1387 /// </summary> 1776 /// </summary>
@@ -1402,5 +1791,180 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1402 return null; 1791 return null;
1403 } 1792 }
1404 #endregion Util 1793 #endregion Util
1794
1795 #region Web Util
1796 /// <summary>
1797 /// Sends json-rpc request with a serializable type.
1798 /// </summary>
1799 /// <returns>
1800 /// OSD Map.
1801 /// </returns>
1802 /// <param name='parameters'>
1803 /// Serializable type .
1804 /// </param>
1805 /// <param name='method'>
1806 /// Json-rpc method to call.
1807 /// </param>
1808 /// <param name='uri'>
1809 /// URI of json-rpc service.
1810 /// </param>
1811 /// <param name='jsonId'>
1812 /// Id for our call.
1813 /// </param>
1814 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1815 {
1816 if (jsonId == null)
1817 throw new ArgumentNullException ("jsonId");
1818 if (uri == null)
1819 throw new ArgumentNullException ("uri");
1820 if (method == null)
1821 throw new ArgumentNullException ("method");
1822 if (parameters == null)
1823 throw new ArgumentNullException ("parameters");
1824
1825 // Prep our payload
1826 OSDMap json = new OSDMap();
1827
1828 json.Add("jsonrpc", OSD.FromString("2.0"));
1829 json.Add("id", OSD.FromString(jsonId));
1830 json.Add("method", OSD.FromString(method));
1831
1832 json.Add("params", OSD.SerializeMembers(parameters));
1833
1834 string jsonRequestData = OSDParser.SerializeJsonString(json);
1835 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1836
1837 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1838
1839 webRequest.ContentType = "application/json-rpc";
1840 webRequest.Method = "POST";
1841
1842 WebResponse webResponse = null;
1843 try
1844 {
1845 using(Stream dataStream = webRequest.GetRequestStream())
1846 dataStream.Write(content,0,content.Length);
1847
1848 webResponse = webRequest.GetResponse();
1849 }
1850 catch (WebException e)
1851 {
1852 Console.WriteLine("Web Error" + e.Message);
1853 Console.WriteLine ("Please check input");
1854 return false;
1855 }
1856
1857 OSDMap mret = new OSDMap();
1858
1859 using (Stream rstream = webResponse.GetResponseStream())
1860 {
1861 try
1862 {
1863 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1864 }
1865 catch (Exception e)
1866 {
1867 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1868 if (webResponse != null)
1869 webResponse.Close();
1870 return false;
1871 }
1872 }
1873
1874 if (webResponse != null)
1875 webResponse.Close();
1876
1877 if (mret.ContainsKey("error"))
1878 return false;
1879
1880 // get params...
1881 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1882 return true;
1883 }
1884
1885 /// <summary>
1886 /// Sends json-rpc request with OSD parameter.
1887 /// </summary>
1888 /// <returns>
1889 /// The rpc request.
1890 /// </returns>
1891 /// <param name='data'>
1892 /// data - incoming as parameters, outgong as result/error
1893 /// </param>
1894 /// <param name='method'>
1895 /// Json-rpc method to call.
1896 /// </param>
1897 /// <param name='uri'>
1898 /// URI of json-rpc service.
1899 /// </param>
1900 /// <param name='jsonId'>
1901 /// If set to <c>true</c> json identifier.
1902 /// </param>
1903 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1904 {
1905 OSDMap map = new OSDMap();
1906
1907 map["jsonrpc"] = "2.0";
1908 if(string.IsNullOrEmpty(jsonId))
1909 map["id"] = UUID.Random().ToString();
1910 else
1911 map["id"] = jsonId;
1912
1913 map["method"] = method;
1914 map["params"] = data;
1915
1916 string jsonRequestData = OSDParser.SerializeJsonString(map);
1917 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1918
1919 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1920 webRequest.ContentType = "application/json-rpc";
1921 webRequest.Method = "POST";
1922
1923 WebResponse webResponse = null;
1924 try
1925 {
1926 using(Stream dataStream = webRequest.GetRequestStream())
1927 dataStream.Write(content,0,content.Length);
1928
1929 webResponse = webRequest.GetResponse();
1930 }
1931 catch (WebException e)
1932 {
1933 Console.WriteLine("Web Error" + e.Message);
1934 Console.WriteLine ("Please check input");
1935 return false;
1936 }
1937
1938 OSDMap response = new OSDMap();
1939
1940 using (Stream rstream = webResponse.GetResponseStream())
1941 {
1942 try
1943 {
1944 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1945 }
1946 catch (Exception e)
1947 {
1948 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1949 if (webResponse != null)
1950 webResponse.Close();
1951 return false;
1952 }
1953 }
1954
1955 if (webResponse != null)
1956 webResponse.Close();
1957
1958 if(response.ContainsKey("error"))
1959 {
1960 data = response["error"];
1961 return false;
1962 }
1963
1964 data = response;
1965
1966 return true;
1967 }
1968 #endregion Web Util
1405 } 1969 }
1406} 1970}
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 817ef85..c0afe7c 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -47,23 +47,23 @@ namespace OpenSim.Region.CoreModules.Framework
47{ 47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CapabilitiesModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CapabilitiesModule")]
49 public class CapabilitiesModule : INonSharedRegionModule, ICapabilitiesModule 49 public class CapabilitiesModule : INonSharedRegionModule, ICapabilitiesModule
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 private string m_showCapsCommandFormat = " {0,-38} {1,-60}\n"; 53 private string m_showCapsCommandFormat = " {0,-38} {1,-60}\n";
54 54
55 protected Scene m_scene; 55 protected Scene m_scene;
56 56
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
64 protected Dictionary<UUID, Dictionary<ulong, string>> m_childrenSeeds 64 protected Dictionary<UUID, Dictionary<ulong, string>> m_childrenSeeds
65 = new Dictionary<UUID, Dictionary<ulong, string>>(); 65 = new Dictionary<UUID, Dictionary<ulong, string>>();
66 66
67 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
68 { 68 {
69 } 69 }
@@ -101,16 +101,16 @@ namespace OpenSim.Region.CoreModules.Framework
101 { 101 {
102 m_scene.UnregisterModuleInterface<ICapabilitiesModule>(this); 102 m_scene.UnregisterModuleInterface<ICapabilitiesModule>(this);
103 } 103 }
104 104
105 public void PostInitialise() 105 public void PostInitialise()
106 { 106 {
107 } 107 }
108 108
109 public void Close() {} 109 public void Close() {}
110 110
111 public string Name 111 public string Name
112 { 112 {
113 get { return "Capabilities Module"; } 113 get { return "Capabilities Module"; }
114 } 114 }
115 115
116 public Type ReplaceableInterface 116 public Type ReplaceableInterface
@@ -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.DebugFormat("[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,44 +191,65 @@ 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);
178 } 215 }
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)
198 m_capsPaths[agent.AgentID] = agent.CapsPath; 246 m_capsPaths[agent.AgentID] = agent.CapsPath;
199 247
200 lock (m_childrenSeeds) 248 lock (m_childrenSeeds)
201 m_childrenSeeds[agent.AgentID] 249 m_childrenSeeds[agent.AgentID]
202 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds); 250 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds);
203 } 251 }
204 252
205 public string GetCapsPath(UUID agentId) 253 public string GetCapsPath(UUID agentId)
206 { 254 {
207 lock (m_capsPaths) 255 lock (m_capsPaths)
@@ -214,7 +262,7 @@ namespace OpenSim.Region.CoreModules.Framework
214 262
215 return null; 263 return null;
216 } 264 }
217 265
218 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID) 266 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID)
219 { 267 {
220 Dictionary<ulong, string> seeds = null; 268 Dictionary<ulong, string> seeds = null;
@@ -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();
@@ -365,8 +414,8 @@ namespace OpenSim.Region.CoreModules.Framework
365 { 414 {
366 receivedStats[sp.Name] = reqHandler.RequestsReceived; 415 receivedStats[sp.Name] = reqHandler.RequestsReceived;
367 handledStats[sp.Name] = reqHandler.RequestsHandled; 416 handledStats[sp.Name] = reqHandler.RequestsHandled;
368 } 417 }
369 else 418 else
370 { 419 {
371 PollServiceEventArgs pollHandler = null; 420 PollServiceEventArgs pollHandler = null;
372 if (caps.TryGetPollHandler(capName, out pollHandler)) 421 if (caps.TryGetPollHandler(capName, out pollHandler))
@@ -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);
@@ -403,7 +454,7 @@ namespace OpenSim.Region.CoreModules.Framework
403 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); 454 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
404 455
405 if (caps == null) 456 if (caps == null)
406 return; 457 return;
407 458
408 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values) 459 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
409 { 460 {
@@ -439,15 +490,17 @@ namespace OpenSim.Region.CoreModules.Framework
439 } 490 }
440 } 491 }
441 ); 492 );
442 493
443 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value)) 494 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value))
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();
@@ -504,13 +559,15 @@ namespace OpenSim.Region.CoreModules.Framework
504 capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled)); 559 capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled));
505 560
506 foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived)) 561 foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived))
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);
@@ -544,12 +601,13 @@ namespace OpenSim.Region.CoreModules.Framework
544 totalRequestsReceived += handler.RequestsReceived; 601 totalRequestsReceived += handler.RequestsReceived;
545 totalRequestsHandled += handler.RequestsHandled; 602 totalRequestsHandled += handler.RequestsHandled;
546 } 603 }
547 604
548 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled); 605 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled);
549 } 606 }
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/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
index 0c632b1..d652f43 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
@@ -53,12 +53,12 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
53 53
54 protected Scene m_scene; 54 protected Scene m_scene;
55 protected IDialogModule m_dialogMod; 55 protected IDialogModule m_dialogMod;
56 56
57 public string Name { get { return "DAExample Module"; } } 57 public string Name { get { return "DAExample Module"; } }
58 public Type ReplaceableInterface { get { return null; } } 58 public Type ReplaceableInterface { get { return null; } }
59 59
60 public void Initialise(IConfigSource source) {} 60 public void Initialise(IConfigSource source) {}
61 61
62 public void AddRegion(Scene scene) 62 public void AddRegion(Scene scene)
63 { 63 {
64 if (ENABLED) 64 if (ENABLED)
@@ -70,22 +70,22 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
70 m_log.DebugFormat("[DA EXAMPLE MODULE]: Added region {0}", m_scene.Name); 70 m_log.DebugFormat("[DA EXAMPLE MODULE]: Added region {0}", m_scene.Name);
71 } 71 }
72 } 72 }
73 73
74 public void RemoveRegion(Scene scene) 74 public void RemoveRegion(Scene scene)
75 { 75 {
76 if (ENABLED) 76 if (ENABLED)
77 { 77 {
78 m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove; 78 m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove;
79 } 79 }
80 } 80 }
81 81
82 public void RegionLoaded(Scene scene) {} 82 public void RegionLoaded(Scene scene) {}
83 83
84 public void Close() 84 public void Close()
85 { 85 {
86 RemoveRegion(m_scene); 86 RemoveRegion(m_scene);
87 } 87 }
88 88
89 protected bool OnSceneGroupMove(UUID groupId, Vector3 delta) 89 protected bool OnSceneGroupMove(UUID groupId, Vector3 delta)
90 { 90 {
91 OSDMap attrs = null; 91 OSDMap attrs = null;
@@ -96,28 +96,28 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
96 96
97 if (!sop.DynAttrs.TryGetStore(Namespace, StoreName, out attrs)) 97 if (!sop.DynAttrs.TryGetStore(Namespace, StoreName, out attrs))
98 attrs = new OSDMap(); 98 attrs = new OSDMap();
99 99
100 OSDInteger newValue; 100 OSDInteger newValue;
101 101
102 // We have to lock on the entire dynamic attributes map to avoid race conditions with serialization code. 102 // We have to lock on the entire dynamic attributes map to avoid race conditions with serialization code.
103 lock (sop.DynAttrs) 103 lock (sop.DynAttrs)
104 { 104 {
105 if (!attrs.ContainsKey("moves")) 105 if (!attrs.ContainsKey("moves"))
106 newValue = new OSDInteger(1); 106 newValue = new OSDInteger(1);
107 else 107 else
108 newValue = new OSDInteger(attrs["moves"].AsInteger() + 1); 108 newValue = new OSDInteger(attrs["moves"].AsInteger() + 1);
109 109
110 attrs["moves"] = newValue; 110 attrs["moves"] = newValue;
111 111
112 sop.DynAttrs.SetStore(Namespace, StoreName, attrs); 112 sop.DynAttrs.SetStore(Namespace, StoreName, attrs);
113 } 113 }
114 114
115 sop.ParentGroup.HasGroupChanged = true; 115 sop.ParentGroup.HasGroupChanged = true;
116 116
117 string msg = string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue); 117 string msg = string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue);
118 m_log.DebugFormat("[DA EXAMPLE MODULE]: {0}", msg); 118 m_log.DebugFormat("[DA EXAMPLE MODULE]: {0}", msg);
119 m_dialogMod.SendGeneralAlert(msg); 119 m_dialogMod.SendGeneralAlert(msg);
120 120
121 return true; 121 return true;
122 } 122 }
123 } 123 }
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
index 166a994..3364cbc 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
@@ -65,11 +65,11 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
65 private Scene m_scene; 65 private Scene m_scene;
66 private IDialogModule m_dialogMod; 66 private IDialogModule m_dialogMod;
67 67
68 public string Name { get { return "DO"; } } 68 public string Name { get { return "DO"; } }
69 public Type ReplaceableInterface { get { return null; } } 69 public Type ReplaceableInterface { get { return null; } }
70 70
71 public void Initialise(IConfigSource source) {} 71 public void Initialise(IConfigSource source) {}
72 72
73 public void AddRegion(Scene scene) 73 public void AddRegion(Scene scene)
74 { 74 {
75 if (ENABLED) 75 if (ENABLED)
@@ -80,18 +80,18 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
80 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); 80 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>();
81 } 81 }
82 } 82 }
83 83
84 public void RemoveRegion(Scene scene) 84 public void RemoveRegion(Scene scene)
85 { 85 {
86 if (ENABLED) 86 if (ENABLED)
87 { 87 {
88 m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove; 88 m_scene.EventManager.OnSceneGroupMove -= OnSceneGroupMove;
89 } 89 }
90 } 90 }
91 91
92 public void RegionLoaded(Scene scene) {} 92 public void RegionLoaded(Scene scene) {}
93 93
94 public void Close() 94 public void Close()
95 { 95 {
96 RemoveRegion(m_scene); 96 RemoveRegion(m_scene);
97 } 97 }
@@ -116,7 +116,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
116 116
117 rootPart.DynObjs.Add(DAExampleModule.Namespace, Name, new MyObject(movesSoFar)); 117 rootPart.DynObjs.Add(DAExampleModule.Namespace, Name, new MyObject(movesSoFar));
118 } 118 }
119 119
120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta) 120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta)
121 { 121 {
122 SceneObjectGroup so = m_scene.GetSceneObjectGroup(groupId); 122 SceneObjectGroup so = m_scene.GetSceneObjectGroup(groupId);
@@ -129,11 +129,11 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
129 if (rawObj != null) 129 if (rawObj != null)
130 { 130 {
131 MyObject myObj = (MyObject)rawObj; 131 MyObject myObj = (MyObject)rawObj;
132 132
133 m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", so.Name, so.UUID, ++myObj.Moves)); 133 m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", so.Name, so.UUID, ++myObj.Moves));
134 } 134 }
135 135
136 return true; 136 return true;
137 } 137 }
138 } 138 }
139} \ No newline at end of file 139} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 1b4b5e6..59e71c6 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -66,9 +66,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
66 /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests. 66 /// If true then we ask the viewer to disable teleport cancellation and ignore teleport requests.
67 /// </summary> 67 /// </summary>
68 /// <remarks> 68 /// <remarks>
69 /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a 69 /// This is useful in situations where teleport is very likely to always succeed and we want to avoid a
70 /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the 70 /// situation where avatars can be come 'stuck' due to a failed teleport cancellation. Unfortunately, the
71 /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport 71 /// nature of the teleport protocol makes it extremely difficult (maybe impossible) to make teleport
72 /// cancellation consistently suceed. 72 /// cancellation consistently suceed.
73 /// </remarks> 73 /// </remarks>
74 public bool DisableInterRegionTeleportCancellation { get; set; } 74 public bool DisableInterRegionTeleportCancellation { get; set; }
@@ -130,7 +130,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
130 { 130 {
131 if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil)) 131 if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
132 { 132 {
133 if (DateTime.Now < m_banUntil) 133 if (DateTime.UtcNow < m_banUntil)
134 { 134 {
135 ret = true; 135 ret = true;
136 } 136 }
@@ -141,13 +141,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
141 // Add this agent in this region as a banned person 141 // Add this agent in this region as a banned person
142 public void Add(ulong pRegionHandle, UUID pAgentID) 142 public void Add(ulong pRegionHandle, UUID pAgentID)
143 { 143 {
144 this.Add(pRegionHandle, pAgentID, 45, 15);
145 }
146
147 public void Add(ulong pRegionHandle, UUID pAgentID, double newTime, double extendTime)
148 {
144 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache)) 149 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
145 { 150 {
146 m_idCache = new ExpiringCache<ulong, DateTime>(); 151 m_idCache = new ExpiringCache<ulong, DateTime>();
147 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45)); 152 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime));
148 } 153 }
149 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 154 m_idCache.Add(pRegionHandle, DateTime.UtcNow + TimeSpan.FromSeconds(extendTime), extendTime);
150 } 155 }
156
151 // Remove the agent from the region's banned list 157 // Remove the agent from the region's banned list
152 public void Remove(ulong pRegionHandle, UUID pAgentID) 158 public void Remove(ulong pRegionHandle, UUID pAgentID)
153 { 159 {
@@ -157,10 +163,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
157 } 163 }
158 } 164 }
159 } 165 }
166
160 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache(); 167 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
161 168
162 private IEventQueue m_eqModule; 169 private IEventQueue m_eqModule;
163 private IRegionCombinerModule m_regionCombinerModule;
164 170
165 #region ISharedRegionModule 171 #region ISharedRegionModule
166 172
@@ -209,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
209 IConfig transferConfig = source.Configs["EntityTransfer"]; 215 IConfig transferConfig = source.Configs["EntityTransfer"];
210 if (transferConfig != null) 216 if (transferConfig != null)
211 { 217 {
212 DisableInterRegionTeleportCancellation 218 DisableInterRegionTeleportCancellation
213 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); 219 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
214 220
215 WaitForAgentArrivedAtDestination 221 WaitForAgentArrivedAtDestination
@@ -232,7 +238,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
232 238
233 Scene = scene; 239 Scene = scene;
234 240
235 m_interRegionTeleportAttempts = 241 m_interRegionTeleportAttempts =
236 new Stat( 242 new Stat(
237 "InterRegionTeleportAttempts", 243 "InterRegionTeleportAttempts",
238 "Number of inter-region teleports attempted.", 244 "Number of inter-region teleports attempted.",
@@ -245,7 +251,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
245 null, 251 null,
246 StatVerbosity.Debug); 252 StatVerbosity.Debug);
247 253
248 m_interRegionTeleportAborts = 254 m_interRegionTeleportAborts =
249 new Stat( 255 new Stat(
250 "InterRegionTeleportAborts", 256 "InterRegionTeleportAborts",
251 "Number of inter-region teleports aborted due to client actions.", 257 "Number of inter-region teleports aborted due to client actions.",
@@ -257,7 +263,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
257 null, 263 null,
258 StatVerbosity.Debug); 264 StatVerbosity.Debug);
259 265
260 m_interRegionTeleportCancels = 266 m_interRegionTeleportCancels =
261 new Stat( 267 new Stat(
262 "InterRegionTeleportCancels", 268 "InterRegionTeleportCancels",
263 "Number of inter-region teleports cancelled by the client.", 269 "Number of inter-region teleports cancelled by the client.",
@@ -269,7 +275,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
269 null, 275 null,
270 StatVerbosity.Debug); 276 StatVerbosity.Debug);
271 277
272 m_interRegionTeleportFailures = 278 m_interRegionTeleportFailures =
273 new Stat( 279 new Stat(
274 "InterRegionTeleportFailures", 280 "InterRegionTeleportFailures",
275 "Number of inter-region teleports that failed due to server/client/network issues.", 281 "Number of inter-region teleports that failed due to server/client/network issues.",
@@ -303,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
303 309
304 public virtual void Close() {} 310 public virtual void Close() {}
305 311
306 public virtual void RemoveRegion(Scene scene) 312 public virtual void RemoveRegion(Scene scene)
307 { 313 {
308 if (m_Enabled) 314 if (m_Enabled)
309 { 315 {
@@ -320,7 +326,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
320 return; 326 return;
321 327
322 m_eqModule = Scene.RequestModuleInterface<IEventQueue>(); 328 m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
323 m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>();
324 } 329 }
325 330
326 #endregion 331 #endregion
@@ -332,7 +337,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
332 if (client.IsLoggingOut && m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting)) 337 if (client.IsLoggingOut && m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting))
333 { 338 {
334 m_log.DebugFormat( 339 m_log.DebugFormat(
335 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", 340 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
336 client.Name, Scene.Name); 341 client.Name, Scene.Name);
337 } 342 }
338 } 343 }
@@ -354,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
354 teleportFlags |= (uint)TeleportFlags.Godlike; 359 teleportFlags |= (uint)TeleportFlags.Godlike;
355 } 360 }
356 361
357 if (!sp.Scene.Permissions.CanTeleport(sp.UUID)) 362 else if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
358 return; 363 return;
359 364
360 string destinationRegionName = "(not found)"; 365 string destinationRegionName = "(not found)";
@@ -374,17 +379,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
374 379
375 try 380 try
376 { 381 {
377 // Reset animations; the viewer does that in teleports.
378 sp.Animator.ResetAnimations();
379 382
380 if (regionHandle == sp.Scene.RegionInfo.RegionHandle) 383 if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
381 { 384 {
385 if(!sp.AllowMovement)
386 {
387 sp.ControllingClient.SendTeleportFailed("You are frozen");
388 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
389 return;
390 }
391
392 // Reset animations; the viewer does that in teleports.
393 sp.Animator.ResetAnimations();
382 destinationRegionName = sp.Scene.RegionInfo.RegionName; 394 destinationRegionName = sp.Scene.RegionInfo.RegionName;
383 395
384 TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags); 396 TeleportAgentWithinRegion(sp, position, lookAt, teleportFlags);
385 } 397 }
386 else // Another region possibly in another simulator 398 else // Another region possibly in another simulator
387 { 399 {
400 // Reset animations; the viewer does that in teleports.
401 sp.Animator.ResetAnimations();
402
388 GridRegion finalDestination = null; 403 GridRegion finalDestination = null;
389 try 404 try
390 { 405 {
@@ -400,12 +415,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
400 } 415 }
401 catch (Exception e) 416 catch (Exception e)
402 { 417 {
418
403 m_log.ErrorFormat( 419 m_log.ErrorFormat(
404 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}", 420 "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}",
405 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, 421 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName,
406 e.Message, e.StackTrace); 422 e.Message, e.StackTrace);
407 423 if(sp != null && sp.ControllingClient != null && !sp.IsDeleted)
408 sp.ControllingClient.SendTeleportFailed("Internal error"); 424 sp.ControllingClient.SendTeleportFailed("Internal error");
409 } 425 }
410 finally 426 finally
411 { 427 {
@@ -438,17 +454,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
438 position = emergencyPos; 454 position = emergencyPos;
439 } 455 }
440 456
457 // Check Default Location (Also See ScenePresence.CompleteMovement)
458 if (position.X == 128f && position.Y == 128f && position.Z == 22.5f)
459 position = sp.Scene.RegionInfo.DefaultLandingPoint;
460
441 // TODO: Get proper AVG Height 461 // TODO: Get proper AVG Height
442 float localAVHeight = 1.56f; 462 float localHalfAVHeight = 0.8f;
463 if (sp.Appearance != null)
464 localHalfAVHeight = sp.Appearance.AvatarHeight / 2;
465
443 float posZLimit = 22; 466 float posZLimit = 22;
444 467
445 // TODO: Check other Scene HeightField 468 // TODO: Check other Scene HeightField
446 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; 469 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
447 470
448 float newPosZ = posZLimit + localAVHeight; 471 posZLimit += localHalfAVHeight + 0.1f;
449 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 472
473 if ((position.Z < posZLimit) && !(Single.IsInfinity(posZLimit) || Single.IsNaN(posZLimit)))
450 { 474 {
451 position.Z = newPosZ; 475 position.Z = posZLimit;
452 } 476 }
453 477
454 if (sp.Flying) 478 if (sp.Flying)
@@ -457,9 +481,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
457 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 481 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
458 482
459 sp.ControllingClient.SendTeleportStart(teleportFlags); 483 sp.ControllingClient.SendTeleportStart(teleportFlags);
484 lookAt.Z = 0f;
485
486 if(Math.Abs(lookAt.X) < 0.01f && Math.Abs(lookAt.Y) < 0.01f)
487 {
488 lookAt.X = 1.0f;
489 lookAt.Y = 0;
490 }
460 491
461 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); 492 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
462 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags; 493 sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags;
494 sp.RotateToLookAt(lookAt);
463 sp.Velocity = Vector3.Zero; 495 sp.Velocity = Vector3.Zero;
464 sp.Teleport(position); 496 sp.Teleport(position);
465 497
@@ -494,15 +526,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
494 { 526 {
495 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId); 527 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId);
496 528
497 string message; 529 string reason = String.Empty;
498 finalDestination = GetFinalDestination(reg, sp.ControllingClient.AgentId, homeURI, out message); 530 finalDestination = GetFinalDestination(reg, sp.ControllingClient.AgentId, homeURI, out reason);
499 531
500 if (finalDestination == null) 532 if (finalDestination == null)
501 { 533 {
502 m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}: {3}", 534 m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}: {3}",
503 LogHeader, sp.Name, sp.UUID, message); 535 LogHeader, sp.Name, sp.UUID, reason);
504 536
505 sp.ControllingClient.SendTeleportFailed(message); 537 sp.ControllingClient.SendTeleportFailed(reason);
506 return; 538 return;
507 } 539 }
508 540
@@ -515,17 +547,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
515 return; 547 return;
516 } 548 }
517 549
518 // Validate assorted conditions
519 string reason = string.Empty;
520 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason)) 550 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
521 { 551 {
522 sp.ControllingClient.SendTeleportFailed(reason); 552 sp.ControllingClient.SendTeleportFailed(reason);
523 return; 553 return;
524 } 554 }
525 555
526 if (message != null)
527 sp.ControllingClient.SendAgentAlertMessage(message, true);
528
529 // 556 //
530 // This is it 557 // This is it
531 // 558 //
@@ -547,9 +574,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
547 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY); 574 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
548 575
549 MapBlockData block = new MapBlockData(); 576 MapBlockData block = new MapBlockData();
550 block.X = (ushort)regX; 577 block.X = (ushort)(regX);
551 block.Y = (ushort)regY; 578 block.Y = (ushort)(regY);
552 block.Access = (byte)SimAccess.Down; 579 block.Access = (byte)SimAccess.Down; // == not there
553 580
554 List<MapBlockData> blocks = new List<MapBlockData>(); 581 List<MapBlockData> blocks = new List<MapBlockData>();
555 blocks.Add(block); 582 blocks.Add(block);
@@ -565,12 +592,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
565 uint x = 0, y = 0; 592 uint x = 0, y = 0;
566 Util.RegionHandleToWorldLoc(regionHandle, out x, out y); 593 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
567 594
595 GridRegion reg;
596
597 // handle legacy HG. linked regions are mapped into y = 0 and have no size information
598 // so we can only search by base handle
599 if( y == 0)
600 {
601 reg = gridService.GetRegionByPosition(scope, (int)x, (int)y);
602 return reg;
603 }
604
568 // Compute the world location we're teleporting to 605 // Compute the world location we're teleporting to
569 double worldX = (double)x + position.X; 606 double worldX = (double)x + position.X;
570 double worldY = (double)y + position.Y; 607 double worldY = (double)y + position.Y;
571 608
572 // Find the region that contains the position 609 // Find the region that contains the position
573 GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY); 610 reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY);
574 611
575 if (reg != null) 612 if (reg != null)
576 { 613 {
@@ -589,7 +626,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
589 return true; 626 return true;
590 } 627 }
591 628
592
593 /// <summary> 629 /// <summary>
594 /// Wraps DoTeleportInternal() and manages the transfer state. 630 /// Wraps DoTeleportInternal() and manages the transfer state.
595 /// </summary> 631 /// </summary>
@@ -607,7 +643,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
607 sp.ControllingClient.SendTeleportFailed("Agent is already in transit."); 643 sp.ControllingClient.SendTeleportFailed("Agent is already in transit.");
608 return; 644 return;
609 } 645 }
610 646
611 try 647 try
612 { 648 {
613 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags); 649 DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
@@ -643,18 +679,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
643 679
644 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId); 680 string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId);
645 681
646 m_log.DebugFormat( 682//// m_log.DebugFormat(
647 "[ENTITY TRANSFER MODULE]: Teleporting {0} {1} from {2} to {3} ({4}) {5}/{6}", 683 m_log.InfoFormat(
648 sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName, 684 "[ENTITY TRANSFER MODULE]: Teleporting {0} {1} from {2}/{3} to {4} ({5}) {6}/{7}",
685 sp.Name, sp.UUID, sp.Scene.RegionInfo.RegionName, sp.AbsolutePosition,
649 reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); 686 reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
650 687
651 RegionInfo sourceRegion = sp.Scene.RegionInfo; 688 RegionInfo sourceRegion = sp.Scene.RegionInfo;
652 689
653
654 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
655 Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
656 Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
657
658 ulong destinationHandle = finalDestination.RegionHandle; 690 ulong destinationHandle = finalDestination.RegionHandle;
659 691
660 // Let's do DNS resolution only once in this process, please! 692 // Let's do DNS resolution only once in this process, please!
@@ -663,8 +695,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
663 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 695 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
664 if (endPoint == null || endPoint.Address == null) 696 if (endPoint == null || endPoint.Address == null)
665 { 697 {
666 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); 698 sp.ControllingClient.SendTeleportFailed("Could not resolve destination Address");
667
668 return; 699 return;
669 } 700 }
670 701
@@ -694,7 +725,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
694 m_interRegionTeleportAttempts.Value++; 725 m_interRegionTeleportAttempts.Value++;
695 726
696 m_log.DebugFormat( 727 m_log.DebugFormat(
697 "[ENTITY TRANSFER MODULE]: {0} transfer protocol version to {1} is {2} / {3}", 728 "[ENTITY TRANSFER MODULE]: {0} transfer protocol version to {1} is {2} / {3}",
698 sp.Scene.Name, finalDestination.RegionName, ctx.OutboundVersion, ctx.InboundVersion); 729 sp.Scene.Name, finalDestination.RegionName, ctx.OutboundVersion, ctx.InboundVersion);
699 730
700 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 731 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
@@ -704,27 +735,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
704 else if (sp.Flying) 735 else if (sp.Flying)
705 teleportFlags |= (uint)TeleportFlags.IsFlying; 736 teleportFlags |= (uint)TeleportFlags.IsFlying;
706 737
738 sp.IsInLocalTransit = finalDestination.RegionLocY != 0; // HG
739 sp.IsInTransit = true;
740
741
707 if (DisableInterRegionTeleportCancellation) 742 if (DisableInterRegionTeleportCancellation)
708 teleportFlags |= (uint)TeleportFlags.DisableCancel; 743 teleportFlags |= (uint)TeleportFlags.DisableCancel;
709 744
710 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to 745 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
711 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). 746 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested).
712 sp.ControllingClient.SendTeleportStart(teleportFlags); 747 sp.ControllingClient.SendTeleportStart(teleportFlags);
713 748
714 // the avatar.Close below will clear the child region list. We need this below for (possibly)
715 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
716 //List<ulong> childRegions = avatar.KnownRegionHandles;
717 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
718 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
719 // once we reach here...
720 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
721
722 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 749 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
723 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); 750 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
724 agentCircuit.startpos = position; 751 agentCircuit.startpos = position;
725 agentCircuit.child = true; 752 agentCircuit.child = true;
753
726 agentCircuit.Appearance = new AvatarAppearance(); 754 agentCircuit.Appearance = new AvatarAppearance();
727 agentCircuit.Appearance.PackLegacyWearables = true; 755 agentCircuit.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
756
728 if (currentAgentCircuit != null) 757 if (currentAgentCircuit != null)
729 { 758 {
730 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; 759 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -735,36 +764,64 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
735 agentCircuit.Id0 = currentAgentCircuit.Id0; 764 agentCircuit.Id0 = currentAgentCircuit.Id0;
736 } 765 }
737 766
738 // if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 767 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
739 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance, 768 Util.RegionHandleToRegionLoc(destinationHandle, out newRegionX, out newRegionY);
740 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY)); 769 Util.RegionHandleToRegionLoc(sourceRegion.RegionHandle, out oldRegionX, out oldRegionY);
741 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY)) 770 int oldSizeX = (int)sourceRegion.RegionSizeX;
771 int oldSizeY = (int)sourceRegion.RegionSizeY;
772 int newSizeX = finalDestination.RegionSizeX;
773 int newSizeY = finalDestination.RegionSizeY;
774
775 bool OutSideViewRange = NeedsNewAgent(sp.RegionViewDistance, oldRegionX, newRegionX, oldRegionY, newRegionY,
776 oldSizeX, oldSizeY, newSizeX, newSizeY);
777
778 if (OutSideViewRange)
742 { 779 {
743 // brand new agent, let's create a new caps seed 780 m_log.DebugFormat(
781 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} size {3},{4} needs new child agent for agent {5} from {6}",
782 finalDestination.RegionName, newRegionX, newRegionY,newSizeX, newSizeY, sp.Name, Scene.Name);
783
784 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
744 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 785 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
745 } 786 }
787 else
788 {
789 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
790 if (agentCircuit.CapsPath == null)
791 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
792 }
746 793
747 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 794 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2
748 if (ctx.OutboundVersion >= 0.2f) 795 if (ctx.OutboundVersion >= 0.2f)
749 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 796 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange , ctx, out reason);
750 else 797 else
751 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 798 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange, ctx, out reason);
752 } 799 }
753 800
754 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 801 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
755 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 802 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
756 { 803 {
757 ulong destinationHandle = finalDestination.RegionHandle; 804 ulong destinationHandle = finalDestination.RegionHandle;
758 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 805 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
759 806
760 m_log.DebugFormat( 807 m_log.DebugFormat(
761 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}", 808 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
762 sp.Name, Scene.Name, finalDestination.RegionName); 809 sp.Name, Scene.Name, finalDestination.RegionName);
763 810
764 // Let's create an agent there if one doesn't exist yet. 811 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
812 List<ulong> childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
813 if(agentCircuit.ChildrenCapSeeds != null)
814 {
815 foreach(ulong handler in childRegionsToClose)
816 {
817 agentCircuit.ChildrenCapSeeds.Remove(handler);
818 }
819 }
820
821 // Let's create an agent there if one doesn't exist yet.
765 // NOTE: logout will always be false for a non-HG teleport. 822 // NOTE: logout will always be false for a non-HG teleport.
766 bool logout = false; 823 bool logout = false;
767 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 824 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
768 { 825 {
769 m_interRegionTeleportFailures.Value++; 826 m_interRegionTeleportFailures.Value++;
770 827
@@ -773,7 +830,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
773 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 830 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
774 831
775 sp.ControllingClient.SendTeleportFailed(reason); 832 sp.ControllingClient.SendTeleportFailed(reason);
776 833 sp.IsInTransit = false;
777 return; 834 return;
778 } 835 }
779 836
@@ -784,7 +841,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
784 m_log.DebugFormat( 841 m_log.DebugFormat(
785 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 842 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
786 sp.Name, finalDestination.RegionName, sp.Scene.Name); 843 sp.Name, finalDestination.RegionName, sp.Scene.Name);
787 844 sp.IsInTransit = false;
788 return; 845 return;
789 } 846 }
790 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 847 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
@@ -794,7 +851,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
794 m_log.DebugFormat( 851 m_log.DebugFormat(
795 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", 852 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
796 sp.Name, finalDestination.RegionName, sp.Scene.Name); 853 sp.Name, finalDestination.RegionName, sp.Scene.Name);
797 854 sp.IsInTransit = false;
798 return; 855 return;
799 } 856 }
800 857
@@ -802,28 +859,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
802 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 859 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
803 860
804 // OK, it got this agent. Let's close some child agents 861 // OK, it got this agent. Let's close some child agents
805 sp.CloseChildAgents(newRegionX, newRegionY);
806 862
807 IClientIPEndpoint ipepClient; 863 if (OutSideViewRange)
808 string capsPath = String.Empty;
809 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
810 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
811 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
812 { 864 {
813 m_log.DebugFormat(
814 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
815 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
816
817 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
818 #region IP Translation for NAT
819 // Uses ipepClient above
820 if (sp.ClientView.TryGet(out ipepClient))
821 {
822 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
823 }
824 #endregion
825 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
826
827 if (m_eqModule != null) 865 if (m_eqModule != null)
828 { 866 {
829 // The EnableSimulator message makes the client establish a connection with the destination 867 // The EnableSimulator message makes the client establish a connection with the destination
@@ -853,22 +891,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
853 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); 891 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
854 } 892 }
855 } 893 }
856 else
857 {
858 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
859 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
860 }
861 894
862 // Let's send a full update of the agent. This is a synchronous call. 895 // Let's send a full update of the agent. This is a synchronous call.
863 AgentData agent = new AgentData(); 896 AgentData agent = new AgentData();
864 sp.CopyTo(agent); 897 sp.CopyTo(agent,false);
865 if (ctx.OutboundVersion < 0.5f) 898
866 agent.Appearance.PackLegacyWearables = true; 899 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
900 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
901
867 agent.Position = agentCircuit.startpos; 902 agent.Position = agentCircuit.startpos;
868 SetCallbackURL(agent, sp.Scene.RegionInfo); 903 SetCallbackURL(agent, sp.Scene.RegionInfo);
869 904
870 905 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
871 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
872 // establish th econnection to the destination which makes it return true. 906 // establish th econnection to the destination which makes it return true.
873 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 907 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
874 { 908 {
@@ -877,15 +911,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
877 m_log.DebugFormat( 911 m_log.DebugFormat(
878 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", 912 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
879 sp.Name, finalDestination.RegionName, sp.Scene.Name); 913 sp.Name, finalDestination.RegionName, sp.Scene.Name);
880 914 sp.IsInTransit = false;
881 return; 915 return;
882 } 916 }
883 917
884 // A common teleport failure occurs when we can send CreateAgent to the 918 // A common teleport failure occurs when we can send CreateAgent to the
885 // destination region but the viewer cannot establish the connection (e.g. due to network issues between 919 // destination region but the viewer cannot establish the connection (e.g. due to network issues between
886 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then 920 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
887 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). 921 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
888 if (!UpdateAgent(reg, finalDestination, agent, sp)) 922 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
889 { 923 {
890 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 924 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
891 { 925 {
@@ -894,7 +928,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
894 m_log.DebugFormat( 928 m_log.DebugFormat(
895 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", 929 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
896 sp.Name, finalDestination.RegionName, sp.Scene.Name); 930 sp.Name, finalDestination.RegionName, sp.Scene.Name);
897 931 sp.IsInTransit = false;
898 return; 932 return;
899 } 933 }
900 934
@@ -903,6 +937,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
903 sp.Name, finalDestination.RegionName, sp.Scene.Name); 937 sp.Name, finalDestination.RegionName, sp.Scene.Name);
904 938
905 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); 939 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
940 sp.IsInTransit = false;
906 return; 941 return;
907 } 942 }
908 943
@@ -915,7 +950,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
915 sp.Name, finalDestination.RegionName, sp.Scene.Name); 950 sp.Name, finalDestination.RegionName, sp.Scene.Name);
916 951
917 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination); 952 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination);
918 953 sp.IsInTransit = false;
919 return; 954 return;
920 } 955 }
921 956
@@ -924,7 +959,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
924 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); 959 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
925 960
926 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, 961 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
927 // where that neighbour simulator could otherwise request a child agent create on the source which then 962 // where that neighbour simulator could otherwise request a child agent create on the source which then
928 // closes our existing agent which is still signalled as root. 963 // closes our existing agent which is still signalled as root.
929 sp.IsChildAgent = true; 964 sp.IsChildAgent = true;
930 965
@@ -952,7 +987,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
952 m_log.DebugFormat( 987 m_log.DebugFormat(
953 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", 988 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
954 sp.Name, finalDestination.RegionName, sp.Scene.Name); 989 sp.Name, finalDestination.RegionName, sp.Scene.Name);
955 990 sp.IsInTransit = false;
956 return; 991 return;
957 } 992 }
958 993
@@ -961,12 +996,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
961 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 996 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
962 997
963 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion."); 998 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
964 999 sp.IsInTransit = false;
965 return; 1000 return;
966 } 1001 }
967 1002
968 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
969
970/* 1003/*
971 // TODO: This may be 0.6. Check if still needed 1004 // TODO: This may be 0.6. Check if still needed
972 // For backwards compatibility 1005 // For backwards compatibility
@@ -978,18 +1011,26 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
978 } 1011 }
979*/ 1012*/
980 1013
981 // May need to logout or other cleanup 1014 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1015
1016 if(logout)
1017 sp.closeAllChildAgents();
1018 else
1019 sp.CloseChildAgents(childRegionsToClose);
1020
1021 // call HG hook
982 AgentHasMovedAway(sp, logout); 1022 AgentHasMovedAway(sp, logout);
983 1023
984 // Well, this is it. The agent is over there. 1024 sp.HasMovedAway(!(OutSideViewRange || logout));
985 KillEntity(sp.Scene, sp.LocalId);
986 1025
987 // Now let's make it officially a child agent 1026// ulong sourceRegionHandle = sp.RegionHandle;
988 sp.MakeChildAgent(); 1027
1028 // Now let's make it officially a child agent
1029 sp.MakeChildAgent(destinationHandle);
989 1030
990 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1031 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
991 1032
992 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1033 if (NeedsClosing(reg, OutSideViewRange))
993 { 1034 {
994 if (!sp.Scene.IncomingPreCloseClient(sp)) 1035 if (!sp.Scene.IncomingPreCloseClient(sp))
995 return; 1036 return;
@@ -1001,26 +1042,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1001 // This sleep can be increased if necessary. However, whilst it's active, 1042 // This sleep can be increased if necessary. However, whilst it's active,
1002 // an agent cannot teleport back to this region if it has teleported away. 1043 // an agent cannot teleport back to this region if it has teleported away.
1003 Thread.Sleep(2000); 1044 Thread.Sleep(2000);
1004
1005 sp.Scene.CloseAgent(sp.UUID, false); 1045 sp.Scene.CloseAgent(sp.UUID, false);
1006 } 1046 }
1007 else 1047 sp.IsInTransit = false;
1008 {
1009 // now we have a child agent in this region.
1010 sp.Reset();
1011 }
1012 } 1048 }
1013 1049
1014 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 1050 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
1015 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 1051 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
1016 { 1052 {
1017 ulong destinationHandle = finalDestination.RegionHandle; 1053 ulong destinationHandle = finalDestination.RegionHandle;
1018 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1019 1054
1020 // Let's create an agent there if one doesn't exist yet. 1055 List<ulong> childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1056
1057 if(agentCircuit.ChildrenCapSeeds != null)
1058 {
1059 foreach(ulong handler in childRegionsToClose)
1060 {
1061 agentCircuit.ChildrenCapSeeds.Remove(handler);
1062 }
1063 }
1064
1065 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);;
1066
1067 // Let's create an agent there if one doesn't exist yet.
1021 // NOTE: logout will always be false for a non-HG teleport. 1068 // NOTE: logout will always be false for a non-HG teleport.
1022 bool logout = false; 1069 bool logout = false;
1023 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 1070 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
1024 { 1071 {
1025 m_interRegionTeleportFailures.Value++; 1072 m_interRegionTeleportFailures.Value++;
1026 1073
@@ -1029,7 +1076,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1029 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 1076 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
1030 1077
1031 sp.ControllingClient.SendTeleportFailed(reason); 1078 sp.ControllingClient.SendTeleportFailed(reason);
1032 1079 sp.IsInTransit = false;
1033 return; 1080 return;
1034 } 1081 }
1035 1082
@@ -1041,6 +1088,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1041 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 1088 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
1042 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1089 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1043 1090
1091 sp.IsInTransit = false;
1044 return; 1092 return;
1045 } 1093 }
1046 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 1094 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
@@ -1051,40 +1099,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1051 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", 1099 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
1052 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1100 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1053 1101
1102 sp.IsInTransit = false;
1054 return; 1103 return;
1055 } 1104 }
1056 1105
1057 // Past this point we have to attempt clean up if the teleport fails, so update transfer state. 1106 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
1058 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 1107 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1059 1108
1060 IClientIPEndpoint ipepClient;
1061 string capsPath = String.Empty;
1062 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
1063 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
1064 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
1065 {
1066 m_log.DebugFormat(
1067 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
1068 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
1069
1070 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
1071 #region IP Translation for NAT
1072 // Uses ipepClient above
1073 if (sp.ClientView.TryGet(out ipepClient))
1074 {
1075 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1076 }
1077 #endregion
1078 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1079 }
1080 else
1081 {
1082 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
1083 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1084 }
1085
1086 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, 1109 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
1087 // where that neighbour simulator could otherwise request a child agent create on the source which then 1110 // where that neighbour simulator could otherwise request a child agent create on the source which then
1088 // closes our existing agent which is still signalled as root. 1111 // closes our existing agent which is still signalled as root.
1089 //sp.IsChildAgent = true; 1112 //sp.IsChildAgent = true;
1090 1113
@@ -1100,13 +1123,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1100 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", 1123 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
1101 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); 1124 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
1102 1125
1103 // Let's send a full update of the agent. 1126 // Let's send a full update of the agent.
1104 AgentData agent = new AgentData(); 1127 AgentData agent = new AgentData();
1105 sp.CopyTo(agent); 1128 sp.CopyTo(agent,false);
1106 if (ctx.OutboundVersion < 0.5f)
1107 agent.Appearance.PackLegacyWearables = true;
1108 agent.Position = agentCircuit.startpos; 1129 agent.Position = agentCircuit.startpos;
1130
1131 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
1132 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1133
1109 agent.SenderWantsToWaitForRoot = true; 1134 agent.SenderWantsToWaitForRoot = true;
1135
1110 //SetCallbackURL(agent, sp.Scene.RegionInfo); 1136 //SetCallbackURL(agent, sp.Scene.RegionInfo);
1111 1137
1112 // Reset the do not close flag. This must be done before the destination opens child connections (here 1138 // Reset the do not close flag. This must be done before the destination opens child connections (here
@@ -1118,7 +1144,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1118 // Send the Update. If this returns true, we know the client has contacted the destination 1144 // Send the Update. If this returns true, we know the client has contacted the destination
1119 // via CompleteMovementIntoRegion, so we can let go. 1145 // via CompleteMovementIntoRegion, so we can let go.
1120 // If it returns false, something went wrong, and we need to abort. 1146 // If it returns false, something went wrong, and we need to abort.
1121 if (!UpdateAgent(reg, finalDestination, agent, sp)) 1147 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
1122 { 1148 {
1123 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 1149 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1124 { 1150 {
@@ -1127,7 +1153,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1127 m_log.DebugFormat( 1153 m_log.DebugFormat(
1128 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", 1154 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
1129 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1155 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1130 1156 sp.IsInTransit = false;
1131 return; 1157 return;
1132 } 1158 }
1133 1159
@@ -1135,31 +1161,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1135 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}", 1161 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
1136 sp.Name, finalDestination.RegionName, sp.Scene.Name); 1162 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1137 1163
1138 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); 1164 Fail(sp, finalDestination, logout, agentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
1165 sp.IsInTransit = false;
1139 return; 1166 return;
1140 } 1167 }
1141 1168
1142 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 1169 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1143 1170
1144 // Need to signal neighbours whether child agents may need closing irrespective of whether this 1171 if(logout)
1145 // one needed closing. We also need to close child agents as quickly as possible to avoid complicated 1172 sp.closeAllChildAgents();
1146 // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back 1173 else
1147 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex 1174 sp.CloseChildAgents(childRegionsToClose);
1148 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are 1175
1149 // abandoned without proper close by viewer but then re-used by an incoming connection. 1176 sp.HasMovedAway(!(OutSideViewRange || logout));
1150 sp.CloseChildAgents(newRegionX, newRegionY);
1151 1177
1152 // May need to logout or other cleanup 1178 //HG hook
1153 AgentHasMovedAway(sp, logout); 1179 AgentHasMovedAway(sp, logout);
1154 1180
1155 // Well, this is it. The agent is over there. 1181// ulong sourceRegionHandle = sp.RegionHandle;
1156 KillEntity(sp.Scene, sp.LocalId);
1157 1182
1158 // Now let's make it officially a child agent 1183 // Now let's make it officially a child agent
1159 sp.MakeChildAgent(); 1184 sp.MakeChildAgent(destinationHandle);
1160 1185
1161 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1186 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1162 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1187 // go by HG hook
1188 if (NeedsClosing(reg, OutSideViewRange))
1163 { 1189 {
1164 if (!sp.Scene.IncomingPreCloseClient(sp)) 1190 if (!sp.Scene.IncomingPreCloseClient(sp))
1165 return; 1191 return;
@@ -1170,21 +1196,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1170 // BEFORE THEY SETTLE IN THE NEW REGION. 1196 // BEFORE THEY SETTLE IN THE NEW REGION.
1171 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR 1197 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR
1172 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS. 1198 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS.
1199
1173 Thread.Sleep(15000); 1200 Thread.Sleep(15000);
1174 1201
1175 // OK, it got this agent. Let's close everything 1202 // OK, it got this agent. Let's close everything
1176 // If we shouldn't close the agent due to some other region renewing the connection 1203 // If we shouldn't close the agent due to some other region renewing the connection
1177 // then this will be handled in IncomingCloseAgent under lock conditions 1204 // then this will be handled in IncomingCloseAgent under lock conditions
1178 m_log.DebugFormat( 1205 m_log.DebugFormat(
1179 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); 1206 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1180 1207
1181 sp.Scene.CloseAgent(sp.UUID, false); 1208 sp.Scene.CloseAgent(sp.UUID, false);
1182 } 1209 }
1183 else 1210 sp.IsInTransit = false;
1184 {
1185 // now we have a child agent in this region.
1186 sp.Reset();
1187 }
1188 } 1211 }
1189 1212
1190 /// <summary> 1213 /// <summary>
@@ -1232,13 +1255,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1232 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); 1255 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
1233 } 1256 }
1234 1257
1235 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 1258 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
1236 { 1259 {
1237 GridRegion source = new GridRegion(Scene.RegionInfo); 1260 GridRegion source = new GridRegion(Scene.RegionInfo);
1238 source.RawServerURI = m_GatekeeperURI; 1261 source.RawServerURI = m_GatekeeperURI;
1239 1262
1240 logout = false; 1263 logout = false;
1241 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, out reason); 1264 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, ctx, out reason);
1242 1265
1243 if (success) 1266 if (success)
1244 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout); 1267 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
@@ -1246,9 +1269,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1246 return success; 1269 return success;
1247 } 1270 }
1248 1271
1249 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) 1272 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp, EntityTransferContext ctx)
1250 { 1273 {
1251 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 1274 return Scene.SimulationService.UpdateAgent(finalDestination, agent, ctx);
1252 } 1275 }
1253 1276
1254 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) 1277 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
@@ -1265,10 +1288,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1265 /// </summary> 1288 /// </summary>
1266 /// <param name='sp'></param> 1289 /// <param name='sp'></param>
1267 /// <param name='logout'></param> 1290 /// <param name='logout'></param>
1291 ///
1292 /// now just a HG hook
1268 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) 1293 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
1269 { 1294 {
1270 if (sp.Scene.AttachmentsModule != null) 1295// if (sp.Scene.AttachmentsModule != null)
1271 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, true); 1296// sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, logout);
1272 } 1297 }
1273 1298
1274 protected void KillEntity(Scene scene, uint localID) 1299 protected void KillEntity(Scene scene, uint localID)
@@ -1276,6 +1301,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1276 scene.SendKillObject(new List<uint> { localID }); 1301 scene.SendKillObject(new List<uint> { localID });
1277 } 1302 }
1278 1303
1304 // HG hook
1279 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message) 1305 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message)
1280 { 1306 {
1281 message = null; 1307 message = null;
@@ -1285,28 +1311,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1285 // This returns 'true' if the new region already has a child agent for our 1311 // This returns 'true' if the new region already has a child agent for our
1286 // incoming agent. The implication is that, if 'false', we have to create the 1312 // incoming agent. The implication is that, if 'false', we have to create the
1287 // child and then teleport into the region. 1313 // child and then teleport into the region.
1288 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) 1314 protected virtual bool NeedsNewAgent(float viewdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY,
1315 int oldsizeX, int oldsizeY, int newsizeX, int newsizeY)
1289 { 1316 {
1290 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 1317 return Util.IsOutsideView(viewdist, oldRegionX, newRegionX, oldRegionY, newRegionY,
1291 { 1318 oldsizeX, oldsizeY, newsizeX, newsizeY);
1292 Vector2 swCorner, neCorner;
1293 GetMegaregionViewRange(out swCorner, out neCorner);
1294
1295 m_log.DebugFormat(
1296 "[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}",
1297 Scene.Name, swCorner, neCorner, newRegionX, newRegionY);
1298
1299 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
1300 }
1301 else
1302 {
1303 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
1304 }
1305 } 1319 }
1306 1320
1307 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 1321 // HG Hook
1322 protected virtual bool NeedsClosing(GridRegion reg, bool OutViewRange)
1323
1308 { 1324 {
1309 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1325 return OutViewRange;
1310 } 1326 }
1311 1327
1312 #endregion 1328 #endregion
@@ -1328,11 +1344,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1328 remoteClient.SendTeleportFailed("The teleport destination could not be found."); 1344 remoteClient.SendTeleportFailed("The teleport destination could not be found.");
1329 return; 1345 return;
1330 } 1346 }
1331 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, 1347 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
1332 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); 1348 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
1333 } 1349 }
1334 1350
1335 #endregion 1351 #endregion
1336 1352
1337 #region Teleport Home 1353 #region Teleport Home
1338 1354
@@ -1366,7 +1382,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1366 client.SendTeleportFailed("Your home region could not be found."); 1382 client.SendTeleportFailed("Your home region could not be found.");
1367 return false; 1383 return false;
1368 } 1384 }
1369 1385
1370 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Home region of {0} is {1} ({2}-{3})", 1386 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Home region of {0} is {1} ({2}-{3})",
1371 client.Name, regionInfo.RegionName, regionInfo.RegionCoordX, regionInfo.RegionCoordY); 1387 client.Name, regionInfo.RegionName, regionInfo.RegionCoordX, regionInfo.RegionCoordY);
1372 1388
@@ -1389,105 +1405,146 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1389 1405
1390 #region Agent Crossings 1406 #region Agent Crossings
1391 1407
1392 // Given a position relative to the current region (which has previously been tested to 1408 public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position,
1393 // see that it is actually outside the current region), find the new region that the 1409 EntityTransferContext ctx, out string reason)
1394 // point is actually in. 1410 {
1395 // Returns the coordinates and information of the new region or 'null' of it doesn't exist. 1411 reason = String.Empty;
1412
1413 UUID agentID = agent.UUID;
1414 ulong destinyHandle = destiny.RegionHandle;
1415
1416 if (m_bannedRegionCache.IfBanned(destinyHandle, agentID))
1417 {
1418 return false;
1419 }
1420
1421 Scene ascene = agent.Scene;
1422 string homeURI = ascene.GetAgentHomeURI(agentID);
1423
1424
1425 if (!ascene.SimulationService.QueryAccess(destiny, agentID, homeURI, false, position,
1426 agent.Scene.GetFormatsOffered(), ctx, out reason))
1427 {
1428 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
1429 return false;
1430 }
1431 return true;
1432 }
1433
1434
1435 // Given a position relative to the current region and outside of it
1436 // find the new region that the point is actually in.
1437 // returns 'null' if new region not found or if information
1438 // and new position relative to it
1439 // now only works for crossings
1440
1396 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, 1441 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos,
1397 EntityTransferContext ctx, out Vector3 newpos, out string failureReason) 1442 EntityTransferContext ctx, out Vector3 newpos, out string failureReason)
1398 { 1443 {
1399 newpos = pos; 1444 newpos = pos;
1400 failureReason = string.Empty; 1445 failureReason = string.Empty;
1401 string homeURI = scene.GetAgentHomeURI(agentID);
1402 1446
1403// m_log.DebugFormat( 1447// m_log.DebugFormat(
1404// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1448// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1405 1449
1406 // Compute world location of the object's position 1450 // Compute world location of the agent's position
1407 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X; 1451 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
1408 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y; 1452 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
1409 1453
1410 // Call the grid service to lookup the region containing the new position. 1454 // Call the grid service to lookup the region containing the new position.
1411 GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, 1455 GridRegion neighbourRegion = GetRegionContainingWorldLocation(
1412 presenceWorldX, presenceWorldY, 1456 scene.GridService, scene.RegionInfo.ScopeID,
1413 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY)); 1457 presenceWorldX, presenceWorldY,
1458 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
1414 1459
1415 if (neighbourRegion != null) 1460 if (neighbourRegion == null)
1461 return null;
1462
1463 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
1416 { 1464 {
1417 // Compute the entity's position relative to the new region 1465 failureReason = "Access Denied or Temporary not possible";
1418 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX), 1466 return null;
1467 }
1468
1469 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1470
1471 // Compute the entity's position relative to the new region
1472 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
1419 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY), 1473 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
1420 pos.Z); 1474 pos.Z);
1421 1475
1422 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID)) 1476 string homeURI = scene.GetAgentHomeURI(agentID);
1423 { 1477
1424 failureReason = "Cannot region cross into banned parcel"; 1478 if (!scene.SimulationService.QueryAccess(
1425 neighbourRegion = null; 1479 neighbourRegion, agentID, homeURI, false, newpos,
1426 } 1480 scene.GetFormatsOffered(), ctx, out failureReason))
1427 else 1481 {
1428 { 1482 // remember the fail
1429 // If not banned, make sure this agent is not in the list. 1483 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1430 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID); 1484 if(String.IsNullOrWhiteSpace(failureReason))
1431 } 1485 failureReason = "Access Denied";
1432 1486 return null;
1433 // Check to see if we have access to the target region.
1434 if (neighbourRegion != null
1435 && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, homeURI, false, newpos, scene.GetFormatsOffered(), ctx, out failureReason))
1436 {
1437 // remember banned
1438 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1439 neighbourRegion = null;
1440 }
1441 } 1487 }
1442 else 1488
1489 return neighbourRegion;
1490 }
1491
1492 public bool Cross(ScenePresence agent, bool isFlying)
1493 {
1494 agent.IsInLocalTransit = true;
1495 agent.IsInTransit = true;
1496 CrossAsyncDelegate d = CrossAsync;
1497 d.BeginInvoke(agent, isFlying, CrossCompleted, d);
1498 return true;
1499 }
1500
1501 private void CrossCompleted(IAsyncResult iar)
1502 {
1503 CrossAsyncDelegate icon = (CrossAsyncDelegate)iar.AsyncState;
1504 ScenePresence agent = icon.EndInvoke(iar);
1505
1506 if(agent == null || agent.IsDeleted)
1507 return;
1508
1509 if(!agent.IsChildAgent)
1443 { 1510 {
1444 // The destination region just doesn't exist 1511 // crossing failed
1445 failureReason = "Cannot cross into non-existent region"; 1512 agent.CrossToNewRegionFail();
1446 } 1513 }
1447
1448 if (neighbourRegion == null)
1449 m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
1450 LogHeader, scene.RegionInfo.RegionName,
1451 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
1452 scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
1453 pos);
1454 else 1514 else
1455 m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>", 1515 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1456 LogHeader, neighbourRegion.RegionName,
1457 neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
1458 newpos.X, newpos.Y);
1459 1516
1460 return neighbourRegion; 1517 agent.IsInTransit = false;
1461 } 1518 }
1462 1519
1463 public bool Cross(ScenePresence agent, bool isFlying) 1520 public ScenePresence CrossAsync(ScenePresence agent, bool isFlying)
1464 { 1521 {
1465 Vector3 newpos; 1522 Vector3 newpos;
1466 EntityTransferContext ctx = new EntityTransferContext(); 1523 EntityTransferContext ctx = new EntityTransferContext();
1467 string failureReason; 1524 string failureReason;
1468 1525
1469 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, 1526 // We need this because of decimal number parsing of the protocols.
1527 Culture.SetCurrentCulture();
1528
1529 Vector3 pos = agent.AbsolutePosition + agent.Velocity * 0.2f;
1530
1531 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos,
1470 ctx, out newpos, out failureReason); 1532 ctx, out newpos, out failureReason);
1471 if (neighbourRegion == null) 1533 if (neighbourRegion == null)
1472 { 1534 {
1473 agent.ControllingClient.SendAlertMessage(failureReason); 1535 if (!agent.IsDeleted && failureReason != String.Empty && agent.ControllingClient != null)
1474 return false; 1536 agent.ControllingClient.SendAlertMessage(failureReason);
1537 return agent;
1475 } 1538 }
1476 1539
1477 agent.IsInTransit = true; 1540// agent.IsInTransit = true;
1478
1479 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
1480 d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, ctx, CrossAgentToNewRegionCompleted, d);
1481 1541
1482 Scene.EventManager.TriggerCrossAgentToNewRegion(agent, isFlying, neighbourRegion); 1542 CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
1483 1543 agent.IsInTransit = false;
1484 return true; 1544 return agent;
1485 } 1545 }
1486 1546
1487 1547 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene);
1488 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY,
1489 Vector3 position,
1490 Scene initiatingScene);
1491 1548
1492 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) 1549 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
1493 { 1550 {
@@ -1506,14 +1563,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1506 Thread.Sleep(10000); 1563 Thread.Sleep(10000);
1507 1564
1508 m_log.DebugFormat( 1565 m_log.DebugFormat(
1509 "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}", 1566 "[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}",
1510 agent.Name, regionX, regionY, position, initiatingScene.Name); 1567 agent.Name, regionX, regionY, position, initiatingScene.Name);
1511 1568
1512 agent.Scene.RequestTeleportLocation( 1569 agent.Scene.RequestTeleportLocation(
1513 agent.ControllingClient, 1570 agent.ControllingClient,
1514 Util.RegionLocToHandle(regionX, regionY), 1571 Util.RegionGridLocToHandle(regionX, regionY),
1515 position, 1572 position,
1516 agent.Lookat, 1573 agent.Lookat,
1517 (uint)Constants.TeleportFlags.ViaLocation); 1574 (uint)Constants.TeleportFlags.ViaLocation);
1518 1575
1519 /* 1576 /*
@@ -1557,15 +1614,71 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1557 icon.EndInvoke(iar); 1614 icon.EndInvoke(iar);
1558 } 1615 }
1559 1616
1560 public bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion) 1617 public bool CrossAgentCreateFarChild(ScenePresence agent, GridRegion neighbourRegion, Vector3 pos, EntityTransferContext ctx)
1561 { 1618 {
1562 if (neighbourRegion == null) 1619 ulong regionhandler = neighbourRegion.RegionHandle;
1620
1621 if(agent.knowsNeighbourRegion(regionhandler))
1622 return true;
1623
1624 string reason;
1625 ulong currentRegionHandler = agent.Scene.RegionInfo.RegionHandle;
1626 GridRegion source = new GridRegion(agent.Scene.RegionInfo);
1627
1628 AgentCircuitData currentAgentCircuit =
1629 agent.Scene.AuthenticateHandler.GetAgentCircuitData(agent.ControllingClient.CircuitCode);
1630 AgentCircuitData agentCircuit = agent.ControllingClient.RequestClientInfo();
1631 agentCircuit.startpos = pos;
1632 agentCircuit.child = true;
1633
1634 agentCircuit.Appearance = new AvatarAppearance();
1635 agentCircuit.Appearance.AvatarHeight = agent.Appearance.AvatarHeight;
1636
1637 if (currentAgentCircuit != null)
1638 {
1639 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
1640 agentCircuit.IPAddress = currentAgentCircuit.IPAddress;
1641 agentCircuit.Viewer = currentAgentCircuit.Viewer;
1642 agentCircuit.Channel = currentAgentCircuit.Channel;
1643 agentCircuit.Mac = currentAgentCircuit.Mac;
1644 agentCircuit.Id0 = currentAgentCircuit.Id0;
1645 }
1646
1647 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1648 agent.AddNeighbourRegion(neighbourRegion, agentCircuit.CapsPath);
1649
1650 IPEndPoint endPoint = neighbourRegion.ExternalEndPoint;
1651 if(endPoint == null)
1652 {
1653 m_log.DebugFormat("CrossAgentCreateFarChild failed to resolve neighbour address {0}", neighbourRegion.ExternalHostName);
1563 return false; 1654 return false;
1564 1655 }
1565 m_entityTransferStateMachine.SetInTransit(agent.UUID); 1656 if (!Scene.SimulationService.CreateAgent(source, neighbourRegion, agentCircuit, (int)TeleportFlags.Default, ctx, out reason))
1657 {
1658 agent.RemoveNeighbourRegion(regionhandler);
1659 return false;
1660 }
1566 1661
1567 agent.RemoveFromPhysicalScene(); 1662 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1663 int newSizeX = neighbourRegion.RegionSizeX;
1664 int newSizeY = neighbourRegion.RegionSizeY;
1568 1665
1666 if (m_eqModule != null)
1667 {
1668 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
1669 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
1670 source.RegionName, agent.Name,
1671 neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, newSizeX, newSizeY , capsPath);
1672
1673 m_eqModule.EnableSimulator(regionhandler,
1674 endPoint, agent.UUID, newSizeX, newSizeY);
1675 m_eqModule.EstablishAgentCommunication(agent.UUID, endPoint, capsPath,
1676 regionhandler, newSizeX, newSizeY);
1677 }
1678 else
1679 {
1680 agent.ControllingClient.InformClientOfNeighbour(regionhandler, endPoint);
1681 }
1569 return true; 1682 return true;
1570 } 1683 }
1571 1684
@@ -1582,37 +1695,56 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1582 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}", 1695 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}",
1583 LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos); 1696 LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos);
1584 1697
1585 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) 1698 if (neighbourRegion == null)
1586 { 1699 {
1587 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: prep failed. Resetting transfer state", LogHeader); 1700 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: invalid destiny", LogHeader);
1588 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1701 return agent;
1589 } 1702 }
1590 1703
1591 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying, ctx)) 1704 IPEndPoint endpoint = neighbourRegion.ExternalEndPoint;
1705 if(endpoint == null)
1706 {
1707 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: failed to resolve neighbour address {0} ",neighbourRegion.ExternalHostName);
1708 return agent;
1709 }
1710
1711 m_entityTransferStateMachine.SetInTransit(agent.UUID);
1712 agent.RemoveFromPhysicalScene();
1713
1714 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, endpoint, isFlying, ctx))
1592 { 1715 {
1593 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); 1716 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
1594 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1717 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1595 } 1718 }
1596
1597 CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, ctx);
1598 } 1719 }
1599 catch (Exception e) 1720 catch (Exception e)
1600 { 1721 {
1601 m_log.Error(string.Format("{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e); 1722 m_log.Error(string.Format("{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e);
1602 } 1723 }
1603
1604 return agent; 1724 return agent;
1605 } 1725 }
1606 1726
1607 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx) 1727 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1728 IPEndPoint endpoint, bool isFlying, EntityTransferContext ctx)
1608 { 1729 {
1730 int ts = Util.EnvironmentTickCount();
1731 bool sucess = true;
1732 string reason = String.Empty;
1733 List<ulong> childRegionsToClose = null;
1609 try 1734 try
1610 { 1735 {
1611 AgentData cAgent = new AgentData(); 1736 AgentData cAgent = new AgentData();
1612 agent.CopyTo(cAgent); 1737 agent.CopyTo(cAgent,true);
1613 if (ctx.OutboundVersion < 0.5f) 1738
1614 cAgent.Appearance.PackLegacyWearables = true;
1615 cAgent.Position = pos; 1739 cAgent.Position = pos;
1740 cAgent.ChildrenCapSeeds = agent.KnownRegions;
1741
1742 childRegionsToClose = agent.GetChildAgentsToClose(neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1743 if(cAgent.ChildrenCapSeeds != null)
1744 {
1745 foreach(ulong regh in childRegionsToClose)
1746 cAgent.ChildrenCapSeeds.Remove(regh);
1747 }
1616 1748
1617 if (isFlying) 1749 if (isFlying)
1618 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; 1750 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
@@ -1623,21 +1755,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1623 // Beyond this point, extra cleanup is needed beyond removing transit state 1755 // Beyond this point, extra cleanup is needed beyond removing transit state
1624 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); 1756 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
1625 1757
1626 if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) 1758 if (sucess && !agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent, ctx))
1759 {
1760 sucess = false;
1761 reason = "agent update failed";
1762 }
1763
1764 if(!sucess)
1627 { 1765 {
1628 // region doesn't take it 1766 // region doesn't take it
1629 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1767 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1630 1768
1631 m_log.WarnFormat( 1769 m_log.WarnFormat(
1632 "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.", 1770 "[ENTITY TRANSFER MODULE]: agent {0} crossing to {1} failed: {2}",
1633 neighbourRegion.RegionName, agent.Name); 1771 agent.Name, neighbourRegion.RegionName, reason);
1634 1772
1635 ReInstantiateScripts(agent); 1773 ReInstantiateScripts(agent);
1636 agent.AddToPhysicalScene(isFlying); 1774 if(agent.ParentID == 0 && agent.ParentUUID == UUID.Zero)
1775 {
1776 agent.AddToPhysicalScene(isFlying);
1777 }
1637 1778
1638 return false; 1779 return false;
1639 } 1780 }
1640 1781
1782 m_log.DebugFormat("[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts));
1641 } 1783 }
1642 catch (Exception e) 1784 catch (Exception e)
1643 { 1785 {
@@ -1649,44 +1791,38 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1649 return false; 1791 return false;
1650 } 1792 }
1651 1793
1652 return true;
1653 }
1654
1655 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1656 bool isFlying, EntityTransferContext ctx)
1657 {
1658 agent.ControllingClient.RequestClientInfo();
1659
1660 string agentcaps; 1794 string agentcaps;
1661 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) 1795 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
1662 { 1796 {
1663 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", 1797 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
1664 neighbourRegion.RegionHandle); 1798 neighbourRegion.RegionHandle);
1665 return; 1799 return false;
1666 } 1800 }
1667 1801
1668 // No turning back 1802 // No turning back
1803
1669 agent.IsChildAgent = true; 1804 agent.IsChildAgent = true;
1670 1805
1671 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); 1806 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
1672 1807
1673 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); 1808 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
1674 1809
1675 Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); 1810 Vector3 vel2 = Vector3.Zero;
1811 if((agent.crossingFlags & 2) != 0)
1812 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0);
1676 1813
1677 if (m_eqModule != null) 1814 if (m_eqModule != null)
1678 { 1815 {
1679 m_eqModule.CrossRegion( 1816 m_eqModule.CrossRegion(
1680 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, 1817 neighbourRegion.RegionHandle, pos, vel2 /* agent.Velocity */,
1681 neighbourRegion.ExternalEndPoint, 1818 endpoint, capsPath, agent.UUID, agent.ControllingClient.SessionId,
1682 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1683 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); 1819 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1684 } 1820 }
1685 else 1821 else
1686 { 1822 {
1687 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader); 1823 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1688 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, 1824 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos, agent.Velocity,
1689 capsPath); 1825 endpoint,capsPath);
1690 } 1826 }
1691 1827
1692 // SUCCESS! 1828 // SUCCESS!
@@ -1695,51 +1831,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1695 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. 1831 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
1696 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1832 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1697 1833
1698 agent.MakeChildAgent(); 1834 if(childRegionsToClose != null)
1699 1835 agent.CloseChildAgents(childRegionsToClose);
1700 // FIXME: Possibly this should occur lower down after other commands to close other agents,
1701 // but not sure yet what the side effects would be.
1702 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1703
1704 // now we have a child agent in this region. Request all interesting data about other (root) agents
1705 agent.SendOtherAgentsAvatarDataToClient();
1706 agent.SendOtherAgentsAppearanceToClient();
1707
1708 // TODO: Check since what version this wasn't needed anymore. May be as old as 0.6
1709/*
1710 // Backwards compatibility. Best effort
1711 if (version == 0f)
1712 {
1713 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1714 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1715 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1716 }
1717*/
1718 // Next, let's close the child agent connections that are too far away.
1719 uint neighbourx;
1720 uint neighboury;
1721 Util.RegionHandleToRegionLoc(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
1722 1836
1723 agent.CloseChildAgents(neighbourx, neighboury); 1837 if((agent.crossingFlags & 8) == 0)
1838 agent.ClearControls(); // don't let attachments delete (called in HasMovedAway) disturb taken controls on viewers
1724 1839
1725 AgentHasMovedAway(agent, false); 1840 agent.HasMovedAway((agent.crossingFlags & 8) == 0);
1726 1841
1727 // the user may change their profile information in other region, 1842 agent.MakeChildAgent(neighbourRegion.RegionHandle);
1728 // so the userinfo in UserProfileCache is not reliable any more, delete it
1729 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
1730// if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1731// {
1732// m_log.DebugFormat(
1733// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1734// }
1735 1843
1736 //m_log.Debug("AFTER CROSS"); 1844 // FIXME: Possibly this should occur lower down after other commands to close other agents,
1737 //Scene.DumpChildrenSeeds(UUID); 1845 // but not sure yet what the side effects would be.
1738 //DumpKnownRegions(); 1846 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1739 1847
1740 return; 1848 return true;
1741 } 1849 }
1742 1850
1743 private void CrossAgentToNewRegionCompleted(IAsyncResult iar) 1851 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
1744 { 1852 {
1745 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState; 1853 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
@@ -1754,7 +1862,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1754 // In any case 1862 // In any case
1755 agent.IsInTransit = false; 1863 agent.IsInTransit = false;
1756 1864
1757 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 1865// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1758 } 1866 }
1759 1867
1760 #endregion 1868 #endregion
@@ -1762,7 +1870,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1762 #region Enable Child Agent 1870 #region Enable Child Agent
1763 1871
1764 /// <summary> 1872 /// <summary>
1765 /// This informs a single neighbouring region about agent "avatar". 1873 /// This informs a single neighbouring region about agent "avatar", and avatar about it
1766 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1874 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1767 /// </summary> 1875 /// </summary>
1768 /// <param name="sp"></param> 1876 /// <param name="sp"></param>
@@ -1771,42 +1879,46 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1771 { 1879 {
1772 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName); 1880 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName);
1773 1881
1882 ulong currentRegionHandler = sp.Scene.RegionInfo.RegionHandle;
1883 ulong regionhandler = region.RegionHandle;
1884
1885 Dictionary<ulong, string> seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1886
1887 if (seeds.ContainsKey(regionhandler))
1888 seeds.Remove(regionhandler);
1889/*
1890 List<ulong> oldregions = new List<ulong>(seeds.Keys);
1891
1892 if (oldregions.Contains(currentRegionHandler))
1893 oldregions.Remove(currentRegionHandler);
1894*/
1895 if (!seeds.ContainsKey(currentRegionHandler))
1896 seeds.Add(currentRegionHandler, sp.ControllingClient.RequestClientInfo().CapsPath);
1897
1774 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 1898 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1775 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 1899 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
1776 agent.BaseFolder = UUID.Zero; 1900 agent.BaseFolder = UUID.Zero;
1777 agent.InventoryFolder = UUID.Zero; 1901 agent.InventoryFolder = UUID.Zero;
1778 agent.startpos = new Vector3(128, 128, 70); 1902 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, region);
1779 agent.child = true; 1903 agent.child = true;
1780 agent.Appearance = new AvatarAppearance(); 1904 agent.Appearance = new AvatarAppearance();
1781 agent.Appearance.PackLegacyWearables = true; 1905 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1782 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1783 1906
1784 agent.ChildrenCapSeeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID)); 1907 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1785 //m_log.DebugFormat("[XXX] Seeds 1 {0}", agent.ChildrenCapSeeds.Count);
1786
1787 if (!agent.ChildrenCapSeeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle))
1788 agent.ChildrenCapSeeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1789 //m_log.DebugFormat("[XXX] Seeds 2 {0}", agent.ChildrenCapSeeds.Count);
1790 1908
1791 sp.AddNeighbourRegion(region.RegionHandle, agent.CapsPath); 1909 seeds.Add(regionhandler, agent.CapsPath);
1792 //foreach (ulong h in agent.ChildrenCapSeeds.Keys)
1793 // m_log.DebugFormat("[XXX] --> {0}", h);
1794 //m_log.DebugFormat("[XXX] Adding {0}", region.RegionHandle);
1795 if (agent.ChildrenCapSeeds.ContainsKey(region.RegionHandle))
1796 {
1797 m_log.WarnFormat(
1798 "[ENTITY TRANSFER]: Overwriting caps seed {0} with {1} for region {2} (handle {3}) for {4} in {5}",
1799 agent.ChildrenCapSeeds[region.RegionHandle], agent.CapsPath,
1800 region.RegionName, region.RegionHandle, sp.Name, Scene.Name);
1801 }
1802 1910
1803 agent.ChildrenCapSeeds[region.RegionHandle] = agent.CapsPath; 1911// agent.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1912 agent.ChildrenCapSeeds = null;
1804 1913
1805 if (sp.Scene.CapsModule != null) 1914 if (sp.Scene.CapsModule != null)
1806 { 1915 {
1807 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, agent.ChildrenCapSeeds); 1916 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1808 } 1917 }
1809 1918
1919 sp.KnownRegions = seeds;
1920 sp.AddNeighbourRegionSizeInfo(region);
1921
1810 if (currentAgentCircuit != null) 1922 if (currentAgentCircuit != null)
1811 { 1923 {
1812 agent.ServiceURLs = currentAgentCircuit.ServiceURLs; 1924 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -1816,7 +1928,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1816 agent.Mac = currentAgentCircuit.Mac; 1928 agent.Mac = currentAgentCircuit.Mac;
1817 agent.Id0 = currentAgentCircuit.Id0; 1929 agent.Id0 = currentAgentCircuit.Id0;
1818 } 1930 }
1819 1931/*
1932 AgentPosition agentpos = null;
1933
1934 if (oldregions.Count > 0)
1935 {
1936 agentpos = new AgentPosition();
1937 agentpos.AgentID = new UUID(sp.UUID.Guid);
1938 agentpos.SessionID = sp.ControllingClient.SessionId;
1939 agentpos.Size = sp.Appearance.AvatarSize;
1940 agentpos.Center = sp.CameraPosition;
1941 agentpos.Far = sp.DrawDistance;
1942 agentpos.Position = sp.AbsolutePosition;
1943 agentpos.Velocity = sp.Velocity;
1944 agentpos.RegionHandle = currentRegionHandler;
1945 agentpos.Throttles = sp.ControllingClient.GetThrottlesPacked(1);
1946 agentpos.ChildrenCapSeeds = seeds;
1947 }
1948*/
1820 IPEndPoint external = region.ExternalEndPoint; 1949 IPEndPoint external = region.ExternalEndPoint;
1821 if (external != null) 1950 if (external != null)
1822 { 1951 {
@@ -1825,7 +1954,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1825 InformClientOfNeighbourCompleted, 1954 InformClientOfNeighbourCompleted,
1826 d); 1955 d);
1827 } 1956 }
1957/*
1958 if(oldregions.Count >0)
1959 {
1960 uint neighbourx;
1961 uint neighboury;
1962 UUID scope = sp.Scene.RegionInfo.ScopeID;
1963 foreach (ulong handler in oldregions)
1964 {
1965 Utils.LongToUInts(handler, out neighbourx, out neighboury);
1966 GridRegion neighbour = sp.Scene.GridService.GetRegionByPosition(scope, (int)neighbourx, (int)neighboury);
1967 sp.Scene.SimulationService.UpdateAgent(neighbour, agentpos);
1968 }
1969 }
1970 */
1828 } 1971 }
1972
1829 #endregion 1973 #endregion
1830 1974
1831 #region Enable Child Agents 1975 #region Enable Child Agents
@@ -1835,167 +1979,175 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1835 1979
1836 /// <summary> 1980 /// <summary>
1837 /// This informs all neighbouring regions about agent "avatar". 1981 /// This informs all neighbouring regions about agent "avatar".
1982 /// and as important informs the avatar about then
1838 /// </summary> 1983 /// </summary>
1839 /// <param name="sp"></param> 1984 /// <param name="sp"></param>
1840 public void EnableChildAgents(ScenePresence sp) 1985 public void EnableChildAgents(ScenePresence sp)
1841 { 1986 {
1987 // assumes that out of view range regions are disconnected by the previus region
1988
1842 List<GridRegion> neighbours = new List<GridRegion>(); 1989 List<GridRegion> neighbours = new List<GridRegion>();
1843 RegionInfo m_regionInfo = sp.Scene.RegionInfo; 1990 Scene spScene = sp.Scene;
1991 RegionInfo m_regionInfo = spScene.RegionInfo;
1844 1992
1845 if (m_regionInfo != null) 1993 if (m_regionInfo != null)
1846 { 1994 {
1847 neighbours = GetNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); 1995 neighbours = GetNeighbors(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
1848 } 1996 }
1849 else 1997 else
1850 { 1998 {
1851 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?"); 1999 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
1852 } 2000 }
1853 2001
1854 /// We need to find the difference between the new regions where there are no child agents 2002 ulong currentRegionHandler = m_regionInfo.RegionHandle;
1855 /// and the regions where there are already child agents. We only send notification to the former.
1856 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
1857 neighbourHandles.Add(sp.Scene.RegionInfo.RegionHandle); // add this region too
1858 List<ulong> previousRegionNeighbourHandles;
1859 2003
1860 if (sp.Scene.CapsModule != null) 2004 LinkedList<ulong> previousRegionNeighbourHandles;
2005 Dictionary<ulong, string> seeds;
2006 ICapabilitiesModule capsModule = spScene.CapsModule;
2007
2008 if (capsModule != null)
1861 { 2009 {
1862 previousRegionNeighbourHandles = 2010 seeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(sp.UUID));
1863 new List<ulong>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID).Keys); 2011 previousRegionNeighbourHandles = new LinkedList<ulong>(seeds.Keys);
1864 } 2012 }
1865 else 2013 else
1866 { 2014 {
1867 previousRegionNeighbourHandles = new List<ulong>(); 2015 seeds = new Dictionary<ulong, string>();
2016 previousRegionNeighbourHandles = new LinkedList<ulong>();
1868 } 2017 }
1869 2018
1870 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles); 2019 IClientAPI spClient = sp.ControllingClient;
1871 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1872 2020
1873// Dump("Current Neighbors", neighbourHandles); 2021 // This will fail if the user aborts login
1874// Dump("Previous Neighbours", previousRegionNeighbourHandles); 2022 try
1875// Dump("New Neighbours", newRegions); 2023 {
1876// Dump("Old Neighbours", oldRegions); 2024 if (!seeds.ContainsKey(currentRegionHandler))
1877 2025 seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath);
1878 /// Update the scene presence's known regions here on this region 2026 }
1879 sp.DropOldNeighbours(oldRegions); 2027 catch
1880 2028 {
1881 /// Collect as many seeds as possible 2029 return;
1882 Dictionary<ulong, string> seeds; 2030 }
1883 if (sp.Scene.CapsModule != null)
1884 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1885 else
1886 seeds = new Dictionary<ulong, string>();
1887 2031
1888 //m_log.Debug(" !!! No. of seeds: " + seeds.Count); 2032 AgentCircuitData currentAgentCircuit =
1889 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle)) 2033 spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1890 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1891 2034
1892 /// Create the necessary child agents
1893 List<AgentCircuitData> cagents = new List<AgentCircuitData>(); 2035 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
2036 List<ulong> newneighbours = new List<ulong>();
2037
1894 foreach (GridRegion neighbour in neighbours) 2038 foreach (GridRegion neighbour in neighbours)
1895 { 2039 {
1896 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2040 ulong handler = neighbour.RegionHandle;
2041
2042 if (previousRegionNeighbourHandles.Contains(handler))
1897 { 2043 {
1898 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 2044 // agent already knows this region
1899 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 2045 previousRegionNeighbourHandles.Remove(handler);
1900 agent.BaseFolder = UUID.Zero; 2046 continue;
1901 agent.InventoryFolder = UUID.Zero; 2047 }
1902 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1903 agent.child = true;
1904 agent.Appearance = new AvatarAppearance();
1905 agent.Appearance.PackLegacyWearables = true;
1906 if (currentAgentCircuit != null)
1907 {
1908 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
1909 agent.IPAddress = currentAgentCircuit.IPAddress;
1910 agent.Viewer = currentAgentCircuit.Viewer;
1911 agent.Channel = currentAgentCircuit.Channel;
1912 agent.Mac = currentAgentCircuit.Mac;
1913 agent.Id0 = currentAgentCircuit.Id0;
1914 }
1915 2048
1916 if (newRegions.Contains(neighbour.RegionHandle)) 2049 if (handler == currentRegionHandler)
1917 { 2050 continue;
1918 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 2051
1919 sp.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath); 2052 // a new region to add
1920 seeds.Add(neighbour.RegionHandle, agent.CapsPath); 2053 AgentCircuitData agent = spClient.RequestClientInfo();
1921 } 2054 agent.BaseFolder = UUID.Zero;
1922 else 2055 agent.InventoryFolder = UUID.Zero;
1923 { 2056 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1924 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle); 2057 agent.child = true;
1925 } 2058 agent.Appearance = new AvatarAppearance();
2059 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1926 2060
1927 cagents.Add(agent); 2061 if (currentAgentCircuit != null)
2062 {
2063 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
2064 agent.IPAddress = currentAgentCircuit.IPAddress;
2065 agent.Viewer = currentAgentCircuit.Viewer;
2066 agent.Channel = currentAgentCircuit.Channel;
2067 agent.Mac = currentAgentCircuit.Mac;
2068 agent.Id0 = currentAgentCircuit.Id0;
1928 } 2069 }
1929 }
1930 2070
1931 /// Update all child agent with everyone's seeds 2071 newneighbours.Add(handler);
1932 foreach (AgentCircuitData a in cagents) 2072 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1933 { 2073 seeds.Add(handler, agent.CapsPath);
1934 a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1935 }
1936 2074
1937 if (sp.Scene.CapsModule != null) 2075 agent.ChildrenCapSeeds = null;
1938 { 2076 cagents.Add(agent);
1939 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1940 } 2077 }
1941 sp.KnownRegions = seeds;
1942 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
1943 //avatar.DumpKnownRegions();
1944 2078
1945 bool newAgent = false; 2079 if (previousRegionNeighbourHandles.Contains(currentRegionHandler))
1946 int count = 0; 2080 previousRegionNeighbourHandles.Remove(currentRegionHandler);
1947 foreach (GridRegion neighbour in neighbours)
1948 {
1949 //m_log.WarnFormat("--> Going to send child agent to {0}", neighbour.RegionName);
1950 // Don't do it if there's already an agent in that region
1951 if (newRegions.Contains(neighbour.RegionHandle))
1952 newAgent = true;
1953 else
1954 newAgent = false;
1955// continue;
1956 2081
1957 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2082 // previousRegionNeighbourHandles now contains regions to forget
1958 { 2083 foreach (ulong handler in previousRegionNeighbourHandles)
1959 try 2084 seeds.Remove(handler);
1960 {
1961 // Let's put this back at sync, so that it doesn't clog
1962 // the network, especially for regions in the same physical server.
1963 // We're really not in a hurry here.
1964 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent);
1965 //InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1966 //d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
1967 // InformClientOfNeighbourCompleted,
1968 // d);
1969 }
1970 2085
1971 catch (ArgumentOutOfRangeException) 2086 /// Update all child agent with everyone's seeds
1972 { 2087 // foreach (AgentCircuitData a in cagents)
1973 m_log.ErrorFormat( 2088 // a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1974 "[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}).",
1975 neighbour.ExternalHostName,
1976 neighbour.RegionHandle,
1977 neighbour.RegionLocX,
1978 neighbour.RegionLocY);
1979 }
1980 catch (Exception e)
1981 {
1982 m_log.ErrorFormat(
1983 "[ENTITY TRANSFER MODULE]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
1984 neighbour.ExternalHostName,
1985 neighbour.RegionHandle,
1986 neighbour.RegionLocX,
1987 neighbour.RegionLocY,
1988 e);
1989 2089
1990 // FIXME: Okay, even though we've failed, we're still going to throw the exception on, 2090 if (capsModule != null)
1991 // since I don't know what will happen if we just let the client continue 2091 capsModule.SetChildrenSeed(sp.UUID, seeds);
1992 2092
1993 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes. 2093 sp.KnownRegions = seeds;
1994 // throw e; 2094 sp.SetNeighbourRegionSizeInfo(neighbours);
2095
2096 if(newneighbours.Count > 0 || previousRegionNeighbourHandles.Count > 0)
2097 {
2098 AgentPosition agentpos = new AgentPosition();
2099 agentpos.AgentID = new UUID(sp.UUID.Guid);
2100 agentpos.SessionID = spClient.SessionId;
2101 agentpos.Size = sp.Appearance.AvatarSize;
2102 agentpos.Center = sp.CameraPosition;
2103 agentpos.Far = sp.DrawDistance;
2104 agentpos.Position = sp.AbsolutePosition;
2105 agentpos.Velocity = sp.Velocity;
2106 agentpos.RegionHandle = currentRegionHandler;
2107 //agentpos.GodLevel = sp.GodLevel;
2108 agentpos.GodData = sp.GodController.State();
2109 agentpos.Throttles = spClient.GetThrottlesPacked(1);
2110 // agentpos.ChildrenCapSeeds = seeds;
2111
2112 Util.FireAndForget(delegate
2113 {
2114 Thread.Sleep(200); // the original delay that was at InformClientOfNeighbourAsync start
2115 int count = 0;
2116 IPEndPoint ipe;
1995 2117
2118 foreach (GridRegion neighbour in neighbours)
2119 {
2120 ulong handler = neighbour.RegionHandle;
2121 try
2122 {
2123 if (newneighbours.Contains(handler))
2124 {
2125 ipe = neighbour.ExternalEndPoint;
2126 if (ipe != null)
2127 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, ipe, true);
2128 else
2129 {
2130 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: lost DNS resolution for neighbour {0}", neighbour.ExternalHostName);
2131 }
2132 count++;
2133 }
2134 else if (!previousRegionNeighbourHandles.Contains(handler))
2135 {
2136 spScene.SimulationService.UpdateAgent(neighbour, agentpos);
2137 }
2138 }
2139 catch (Exception e)
2140 {
2141 m_log.ErrorFormat(
2142 "[ENTITY TRANSFER MODULE]: Error creating child agent at {0} ({1} ({2}, {3}). {4}",
2143 neighbour.ExternalHostName,
2144 neighbour.RegionHandle,
2145 neighbour.RegionLocX,
2146 neighbour.RegionLocY,
2147 e);
2148 }
1996 } 2149 }
1997 } 2150 });
1998 count++;
1999 } 2151 }
2000 } 2152 }
2001 2153
@@ -2004,26 +2156,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2004 // The first region is the home region of the passed scene presence. 2156 // The first region is the home region of the passed scene presence.
2005 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2157 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
2006 { 2158 {
2007 /* 2159 return new Vector3(sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2008 int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
2009 int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
2010 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
2011 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
2012 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
2013 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
2014 return new Vector3(shiftx, shifty, 0f);
2015 */
2016 return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2017 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY, 2160 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
2018 0f); 2161 0f);
2019 } 2162 }
2020 2163 #endregion
2021 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2022 {
2023 // Since we don't know how big the regions could be, we have to search a very large area
2024 // to find possible regions.
2025 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2026 }
2027 2164
2028 #region NotFoundLocationCache class 2165 #region NotFoundLocationCache class
2029 // A collection of not found locations to make future lookups 'not found' lookups quick. 2166 // A collection of not found locations to make future lookups 'not found' lookups quick.
@@ -2032,162 +2169,131 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2032 // contains that point. A conservitive estimate. 2169 // contains that point. A conservitive estimate.
2033 private class NotFoundLocationCache 2170 private class NotFoundLocationCache
2034 { 2171 {
2035 private struct NotFoundLocation 2172 private Dictionary<ulong, DateTime> m_notFoundLocations = new Dictionary<ulong, DateTime>();
2036 {
2037 public double minX, maxX, minY, maxY;
2038 public DateTime expireTime;
2039 }
2040 private List<NotFoundLocation> m_notFoundLocations = new List<NotFoundLocation>();
2041 public NotFoundLocationCache() 2173 public NotFoundLocationCache()
2042 { 2174 {
2043 } 2175 }
2044 // Add an area to the list of 'not found' places. The area is the snapped region 2176 // just use normal regions handlers and sizes
2045 // area around the added point.
2046 public void Add(double pX, double pY) 2177 public void Add(double pX, double pY)
2047 { 2178 {
2179 ulong psh = (ulong)pX & 0xffffff00ul;
2180 psh <<= 32;
2181 psh |= (ulong)pY & 0xffffff00ul;
2182
2048 lock (m_notFoundLocations) 2183 lock (m_notFoundLocations)
2049 { 2184 m_notFoundLocations[psh] = DateTime.UtcNow + TimeSpan.FromSeconds(30);
2050 if (!LockedContains(pX, pY))
2051 {
2052 NotFoundLocation nfl = new NotFoundLocation();
2053 // A not found location is not found for at least a whole region sized area
2054 nfl.minX = pX - (pX % (double)Constants.RegionSize);
2055 nfl.minY = pY - (pY % (double)Constants.RegionSize);
2056 nfl.maxX = nfl.minX + (double)Constants.RegionSize;
2057 nfl.maxY = nfl.minY + (double)Constants.RegionSize;
2058 nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
2059 m_notFoundLocations.Add(nfl);
2060 }
2061 }
2062
2063 } 2185 }
2064 // Test to see of this point is in any of the 'not found' areas. 2186 // Test to see of this point is in any of the 'not found' areas.
2065 // Return 'true' if the point is found inside the 'not found' areas. 2187 // Return 'true' if the point is found inside the 'not found' areas.
2066 public bool Contains(double pX, double pY) 2188 public bool Contains(double pX, double pY)
2067 { 2189 {
2068 bool ret = false; 2190 ulong psh = (ulong)pX & 0xffffff00ul;
2191 psh <<= 32;
2192 psh |= (ulong)pY & 0xffffff00ul;
2193
2069 lock (m_notFoundLocations) 2194 lock (m_notFoundLocations)
2070 ret = LockedContains(pX, pY);
2071 return ret;
2072 }
2073 private bool LockedContains(double pX, double pY)
2074 {
2075 bool ret = false;
2076 this.DoExpiration();
2077 foreach (NotFoundLocation nfl in m_notFoundLocations)
2078 { 2195 {
2079 if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY) 2196 if(m_notFoundLocations.ContainsKey(psh))
2080 { 2197 {
2081 ret = true; 2198 if(m_notFoundLocations[psh] > DateTime.UtcNow)
2082 break; 2199 return true;
2200 m_notFoundLocations.Remove(psh);
2083 } 2201 }
2202 return false;
2084 } 2203 }
2085 return ret;
2086 } 2204 }
2205
2087 private void DoExpiration() 2206 private void DoExpiration()
2088 { 2207 {
2089 List<NotFoundLocation> m_toRemove = null; 2208 List<ulong> m_toRemove = new List<ulong>();;
2090 DateTime now = DateTime.Now; 2209 DateTime now = DateTime.UtcNow;
2091 foreach (NotFoundLocation nfl in m_notFoundLocations) 2210 lock (m_notFoundLocations)
2092 { 2211 {
2093 if (nfl.expireTime < now) 2212 foreach (KeyValuePair<ulong, DateTime> kvp in m_notFoundLocations)
2094 { 2213 {
2095 if (m_toRemove == null) 2214 if (kvp.Value < now)
2096 m_toRemove = new List<NotFoundLocation>(); 2215 m_toRemove.Add(kvp.Key);
2097 m_toRemove.Add(nfl); 2216 }
2217
2218 if (m_toRemove.Count > 0)
2219 {
2220 foreach (ulong u in m_toRemove)
2221 m_notFoundLocations.Remove(u);
2222 m_toRemove.Clear();
2098 } 2223 }
2099 }
2100 if (m_toRemove != null)
2101 {
2102 foreach (NotFoundLocation nfl in m_toRemove)
2103 m_notFoundLocations.Remove(nfl);
2104 m_toRemove.Clear();
2105 } 2224 }
2106 } 2225 }
2107 } 2226 }
2227
2108 #endregion // NotFoundLocationCache class 2228 #endregion // NotFoundLocationCache class
2229 #region getregions
2109 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache(); 2230 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2110 2231
2111 // Given a world position (fractional meter coordinate), get the GridRegion info for 2232 protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2233 {
2234 // Since we don't know how big the regions could be, we have to search a very large area
2235 // to find possible regions.
2236 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2237 }
2238
2239 // Given a world position, get the GridRegion info for
2112 // the region containing that point. 2240 // the region containing that point.
2113 // Someday this should be a method on GridService. 2241 // for compatibility with old grids it does a scan to find large regions
2114 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere 2242 // 0.9 grids to that
2115 // the size of the target region is unknown thus the search area might have to be very large. 2243
2116 // Return 'null' if no such region exists. 2244 protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2117 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2118 double px, double py, uint pSizeHint) 2245 double px, double py, uint pSizeHint)
2119 { 2246 {
2120 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: query, loc=<{1},{2}>", LogHeader, px, py); 2247// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2121 GridRegion ret = null; 2248 GridRegion ret = null;
2122 const double fudge = 2.0;
2123 2249
2124 // One problem with this routine is negative results. That is, this can be called lots of times
2125 // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
2126 // will be quick 'not found's next time.
2127 // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
2128 // thus re-ask the GridService about the location.
2129 if (m_notFoundLocationCache.Contains(px, py)) 2250 if (m_notFoundLocationCache.Contains(px, py))
2130 { 2251 {
2131 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py); 2252// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
2132 return null; 2253 return null;
2133 } 2254 }
2134 2255
2135 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get 2256 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
2136 // the region at the appropriate legacy region location. 2257 // the region at the appropriate legacy region location.
2137 uint possibleX = (uint)Math.Floor(px); 2258 // this is all that is needed on 0.9 grids
2138 possibleX -= possibleX % Constants.RegionSize; 2259 uint possibleX = (uint)px & 0xffffff00u;
2139 uint possibleY = (uint)Math.Floor(py); 2260 uint possibleY = (uint)py & 0xffffff00u;
2140 possibleY -= possibleY % Constants.RegionSize;
2141 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY); 2261 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
2142 if (ret != null) 2262 if (ret != null)
2143 { 2263 {
2144 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}", 2264// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
2145 LogHeader, possibleX, possibleY, ret.RegionName); 2265// LogHeader, possibleX, possibleY, ret.RegionName);
2266 return ret;
2146 } 2267 }
2147 2268
2148 if (ret == null) 2269 // for 0.8 regions just make a BIG area request. old code whould do it plus 4 more smaller on region open edges
2270 // this is what 0.9 grids now do internally
2271 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
2272 (int)(px - Constants.MaximumRegionSize), (int)(px + 1), // +1 bc left mb not part of range
2273 (int)(py - Constants.MaximumRegionSize), (int)(py + 1));
2274// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2275// LogHeader, possibleRegions.Count, range);
2276 if (possibleRegions != null && possibleRegions.Count > 0)
2149 { 2277 {
2150 // If the simple lookup failed, search the larger area for a region that contains this point 2278 // If we found some regions, check to see if the point is within
2151 double range = (double)pSizeHint + fudge; 2279 foreach (GridRegion gr in possibleRegions)
2152 while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
2153 { 2280 {
2154 // Get from the grid service a list of regions that might contain this point. 2281// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2155 // The region origin will be in the zero direction so only subtract the range. 2282// LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2156 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID, 2283 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2157 (int)(px - range), (int)(px),
2158 (int)(py - range), (int)(py));
2159 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2160 LogHeader, possibleRegions.Count, range);
2161 if (possibleRegions != null && possibleRegions.Count > 0)
2162 {
2163 // If we found some regions, check to see if the point is within
2164 foreach (GridRegion gr in possibleRegions)
2165 {
2166 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2167 LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2168 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2169 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY)) 2284 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
2170 { 2285 {
2171 // Found a region that contains the point 2286 // Found a region that contains the point
2172 ret = gr; 2287 return gr;
2173 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName); 2288// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
2174 break;
2175 }
2176 }
2177 } 2289 }
2178 // Larger search area for next time around if not found
2179 range *= 2;
2180 } 2290 }
2181 } 2291 }
2182 2292
2183 if (ret == null) 2293 // remember this location was not found so we can quickly not find it next time
2184 { 2294 m_notFoundLocationCache.Add(px, py);
2185 // remember this location was not found so we can quickly not find it next time 2295// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2186 m_notFoundLocationCache.Add(px, py); 2296 return null;
2187 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2188 }
2189
2190 return ret;
2191 } 2297 }
2192 2298
2193 private void InformClientOfNeighbourCompleted(IAsyncResult iar) 2299 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2207,81 +2313,65 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2207 /// <param name="a"></param> 2313 /// <param name="a"></param>
2208 /// <param name="regionHandle"></param> 2314 /// <param name="regionHandle"></param>
2209 /// <param name="endPoint"></param> 2315 /// <param name="endPoint"></param>
2210 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg, 2316 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData agentCircData, GridRegion reg,
2211 IPEndPoint endPoint, bool newAgent) 2317 IPEndPoint endPoint, bool newAgent)
2212 { 2318 {
2213 // Let's wait just a little to give time to originating regions to catch up with closing child agents
2214 // after a cross here
2215 Thread.Sleep(500);
2216 2319
2217 Scene scene = sp.Scene; 2320 if (newAgent)
2218 2321 {
2219 m_log.DebugFormat( 2322 // we may already had lost this sp
2220 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})", 2323 if(sp == null || sp.IsDeleted || sp.ClientView == null) // something bad already happened
2221 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY); 2324 return;
2222 2325
2223 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); 2326 Scene scene = sp.Scene;
2224 2327
2225 string reason = String.Empty; 2328 m_log.DebugFormat(
2329 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
2330 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
2226 2331
2227 bool regionAccepted = scene.SimulationService.CreateAgent(null, reg, a, (uint)TeleportFlags.Default, out reason); 2332 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(agentCircData.CapsPath);
2228 2333
2229 if (regionAccepted && newAgent) 2334 string reason = String.Empty;
2230 { 2335
2231 if (m_eqModule != null) 2336 EntityTransferContext ctx = new EntityTransferContext();
2337 bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, agentCircData, (uint)TeleportFlags.Default, ctx, out reason);
2338
2339 if (regionAccepted)
2232 { 2340 {
2233 #region IP Translation for NAT 2341 // give time for createAgent to finish, since it is async and does grid services access
2234 IClientIPEndpoint ipepClient; 2342 Thread.Sleep(500);
2235 if (sp.ClientView.TryGet(out ipepClient)) 2343
2344 if (m_eqModule != null)
2236 { 2345 {
2237 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); 2346 if(sp == null || sp.IsDeleted || sp.ClientView == null) // something bad already happened
2238 } 2347 return;
2239 #endregion 2348
2349 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
2350 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
2351 scene.RegionInfo.RegionName, sp.Name,
2352 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY, capsPath);
2240 2353
2241 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + 2354 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
2242 "and EstablishAgentCommunication with seed cap {8}", LogHeader, 2355 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
2243 scene.RegionInfo.RegionName, sp.Name, 2356 }
2244 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY , capsPath); 2357 else
2358 {
2359 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
2360 // TODO: make Event Queue disablable!
2361 }
2245 2362
2246 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY); 2363 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
2247 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
2248 } 2364 }
2365
2249 else 2366 else
2250 { 2367 {
2251 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint); 2368 sp.RemoveNeighbourRegion(reg.RegionHandle);
2252 // TODO: make Event Queue disablable! 2369 m_log.WarnFormat(
2370 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2371 reg.RegionName, sp.Name, sp.UUID, reason);
2253 } 2372 }
2254
2255 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
2256 } 2373 }
2257 2374
2258 if (!regionAccepted)
2259 m_log.WarnFormat(
2260 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2261 reg.RegionName, sp.Name, sp.UUID, reason);
2262 }
2263
2264 /// <summary>
2265 /// Gets the range considered in view of this megaregion (assuming this is a megaregion).
2266 /// </summary>
2267 /// <remarks>Expressed in 256m units</remarks>
2268 /// <param name='swCorner'></param>
2269 /// <param name='neCorner'></param>
2270 private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
2271 {
2272 Vector2 extent = Vector2.Zero;
2273
2274 if (m_regionCombinerModule != null)
2275 {
2276 Vector2 megaRegionSize = m_regionCombinerModule.GetSizeOfMegaregion(Scene.RegionInfo.RegionID);
2277 extent.X = (float)Util.WorldToRegionLoc((uint)megaRegionSize.X);
2278 extent.Y = (float)Util.WorldToRegionLoc((uint)megaRegionSize.Y);
2279 }
2280
2281 swCorner.X = Scene.RegionInfo.RegionLocX - 1;
2282 swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
2283 neCorner.X = Scene.RegionInfo.RegionLocX + extent.X;
2284 neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y;
2285 } 2375 }
2286 2376
2287 /// <summary> 2377 /// <summary>
@@ -2290,98 +2380,42 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2290 /// <param name="avatar"></param> 2380 /// <param name="avatar"></param>
2291 /// <param name="pRegionLocX"></param> 2381 /// <param name="pRegionLocX"></param>
2292 /// <param name="pRegionLocY"></param> 2382 /// <param name="pRegionLocY"></param>
2293 /// <returns></returns> 2383 /// <returns></returns>
2294 protected List<GridRegion> GetNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) 2384 protected List<GridRegion> GetNeighbors(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
2295 { 2385 {
2296 Scene pScene = avatar.Scene; 2386 Scene pScene = avatar.Scene;
2297 RegionInfo m_regionInfo = pScene.RegionInfo; 2387 RegionInfo m_regionInfo = pScene.RegionInfo;
2298 List<GridRegion> neighbours; 2388 List<GridRegion> neighbours;
2299 2389
2300 // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't 2390 uint dd = (uint)avatar.RegionViewDistance;
2301 // clear what should be done with a "far view" given that megaregions already extended the
2302 // view to include everything in the megaregion
2303 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
2304 {
2305 // The area to check is as big as the current region.
2306 // We presume all adjacent regions are the same size as this region.
2307 uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
2308 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2309 2391
2310 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2; 2392 // until avatar movement updates client connections, we need to seend at least this current region imediate neighbors
2311 uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2; 2393 uint ddX = Math.Max(dd, Constants.RegionSize);
2394 uint ddY = Math.Max(dd, Constants.RegionSize);
2312 2395
2313 uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2; 2396 ddX--;
2314 uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2; 2397 ddY--;
2315 2398
2316 neighbours 2399 // reference to region edges. Should be avatar position
2317 = avatar.Scene.GridService.GetRegionRange( 2400 uint startX = Util.RegionToWorldLoc(pRegionLocX);
2318 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); 2401 uint endX = startX + m_regionInfo.RegionSizeX;
2319 } 2402 uint startY = Util.RegionToWorldLoc(pRegionLocY);
2320 else 2403 uint endY = startY + m_regionInfo.RegionSizeY;
2321 {
2322 Vector2 swCorner, neCorner;
2323 GetMegaregionViewRange(out swCorner, out neCorner);
2324 2404
2325 neighbours 2405 startX -= ddX;
2326 = pScene.GridService.GetRegionRange( 2406 startY -= ddY;
2327 m_regionInfo.ScopeID, 2407 endX += ddX;
2328 (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X), 2408 endY += ddY;
2329 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
2330 }
2331 2409
2332// neighbours.ForEach( 2410 neighbours
2333// n => 2411 = avatar.Scene.GridService.GetRegionRange(
2334// m_log.DebugFormat( 2412 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
2335// "[ENTITY TRANSFER MODULE]: Region flags for {0} as seen by {1} are {2}",
2336// n.RegionName, Scene.Name, n.RegionFlags != null ? n.RegionFlags.ToString() : "not present"));
2337 2413
2338 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1). 2414 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1).
2339 neighbours.RemoveAll( 2415 neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
2340 r =>
2341 r.RegionID == m_regionInfo.RegionID
2342 || (r.RegionFlags != null && (r.RegionFlags & OpenSim.Framework.RegionFlags.RegionOnline) == 0));
2343 2416
2344 return neighbours; 2417 return neighbours;
2345 } 2418 }
2346
2347 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
2348 {
2349 return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
2350 }
2351
2352 // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
2353 // {
2354 // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
2355 // }
2356
2357 private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
2358 {
2359 return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
2360 }
2361
2362 private List<ulong> NeighbourHandles(List<GridRegion> neighbours)
2363 {
2364 List<ulong> handles = new List<ulong>();
2365 foreach (GridRegion reg in neighbours)
2366 {
2367 handles.Add(reg.RegionHandle);
2368 }
2369 return handles;
2370 }
2371
2372// private void Dump(string msg, List<ulong> handles)
2373// {
2374// m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg);
2375// foreach (ulong handle in handles)
2376// {
2377// uint x, y;
2378// Utils.LongToUInts(handle, out x, out y);
2379// x = x / Constants.RegionSize;
2380// y = y / Constants.RegionSize;
2381// m_log.InfoFormat("({0}, {1})", x, y);
2382// }
2383// }
2384
2385 #endregion 2419 #endregion
2386 2420
2387 #region Agent Arrived 2421 #region Agent Arrived
@@ -2395,83 +2429,47 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2395 2429
2396 #region Object Transfers 2430 #region Object Transfers
2397 2431
2398 /// <summary> 2432 public GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition,out Vector3 newpos)
2399 /// Move the given scene object into a new region depending on which region its absolute position has moved
2400 /// into.
2401 ///
2402 /// Using the objects new world location, ask the grid service for a the new region and adjust the prim
2403 /// position to be relative to the new region.
2404 /// </summary>
2405 /// <param name="grp">the scene object that we're crossing</param>
2406 /// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is
2407 /// relative to the region the object currently is in.</param>
2408 /// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param>
2409 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
2410 { 2433 {
2411 if (grp == null) 2434 newpos = targetPosition;
2412 return;
2413 if (grp.IsDeleted)
2414 return;
2415 2435
2416 Scene scene = grp.Scene; 2436 Scene scene = grp.Scene;
2417 if (scene == null) 2437 if (scene == null)
2418 return; 2438 return null;
2419
2420 if (grp.RootPart.DIE_AT_EDGE)
2421 {
2422 // We remove the object here
2423 try
2424 {
2425 scene.DeleteSceneObject(grp, false);
2426 }
2427 catch (Exception)
2428 {
2429 m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
2430 }
2431 return;
2432 }
2433
2434 // Remember the old group position in case the region lookup fails so position can be restored.
2435 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
2436 2439
2437 // Compute the absolute position of the object. 2440 int x = (int)targetPosition.X + (int)scene.RegionInfo.WorldLocX;
2438 double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X; 2441 if (targetPosition.X >= 0)
2439 double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y; 2442 x++;
2443 else
2444 x--;
2440 2445
2441 // Ask the grid service for the region that contains the passed address 2446 int y = (int)targetPosition.Y + (int)scene.RegionInfo.WorldLocY;
2442 GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, 2447 if (targetPosition.Y >= 0)
2443 objectWorldLocX, objectWorldLocY); 2448 y++;
2449 else
2450 y--;
2444 2451
2445 Vector3 pos = Vector3.Zero; 2452 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID,x,y);
2446 if (destination != null) 2453 if (neighbourRegion == null)
2447 { 2454 {
2448 // Adjust the object's relative position from the old region (attemptedPosition) 2455 return null;
2449 // to be relative to the new region (pos).
2450 pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
2451 (float)(objectWorldLocY - (double)destination.RegionLocY),
2452 attemptedPosition.Z);
2453 } 2456 }
2454 2457
2455 if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) 2458 float newRegionSizeX = neighbourRegion.RegionSizeX;
2456 { 2459 float newRegionSizeY = neighbourRegion.RegionSizeY;
2457 m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID); 2460 if (newRegionSizeX == 0)
2458 2461 newRegionSizeX = Constants.RegionSize;
2459 // We are going to move the object back to the old position so long as the old position 2462 if (newRegionSizeY == 0)
2460 // is in the region 2463 newRegionSizeY = Constants.RegionSize;
2461 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
2462 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
2463 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
2464 2464
2465 grp.AbsolutePosition = oldGroupPosition; 2465 newpos.X = targetPosition.X - (neighbourRegion.RegionLocX - (int)scene.RegionInfo.WorldLocX);
2466 grp.Velocity = Vector3.Zero; 2466 newpos.Y = targetPosition.Y - (neighbourRegion.RegionLocY - (int)scene.RegionInfo.WorldLocY);
2467 if (grp.RootPart.PhysActor != null)
2468 grp.RootPart.PhysActor.CrossingFailure();
2469 2467
2470 if (grp.RootPart.KeyframeMotion != null) 2468 const float enterDistance = 0.2f;
2471 grp.RootPart.KeyframeMotion.CrossingFailure(); 2469 newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
2470 newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
2472 2471
2473 grp.ScheduleGroupForFullUpdate(); 2472 return neighbourRegion;
2474 }
2475 } 2473 }
2476 2474
2477 /// <summary> 2475 /// <summary>
@@ -2483,10 +2481,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2483 /// true if the crossing itself was successful, false on failure 2481 /// true if the crossing itself was successful, false on failure
2484 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region 2482 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
2485 /// </returns> 2483 /// </returns>
2486 protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent) 2484 public bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts)
2487 { 2485 {
2488 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<"); 2486 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");
2489 2487
2488 Culture.SetCurrentCulture();
2489
2490 bool successYN = false; 2490 bool successYN = false;
2491 grp.RootPart.ClearUpdateSchedule(); 2491 grp.RootPart.ClearUpdateSchedule();
2492 //int primcrossingXMLmethod = 0; 2492 //int primcrossingXMLmethod = 0;
@@ -2515,7 +2515,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2515 // We remove the object here 2515 // We remove the object here
2516 try 2516 try
2517 { 2517 {
2518 grp.Scene.DeleteSceneObject(grp, silent); 2518 grp.Scene.DeleteSceneObject(grp, silent, removeScripts);
2519 } 2519 }
2520 catch (Exception e) 2520 catch (Exception e)
2521 { 2521 {
@@ -2524,30 +2524,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2524 grp, e); 2524 grp, e);
2525 } 2525 }
2526 } 2526 }
2527/*
2528 * done on caller ( not in attachments crossing for now)
2529 else
2530 {
2531
2532 if (!grp.IsDeleted)
2533 {
2534 PhysicsActor pa = grp.RootPart.PhysActor;
2535 if (pa != null)
2536 {
2537 pa.CrossingFailure();
2538 if (grp.RootPart.KeyframeMotion != null)
2539 {
2540 // moved to KeyframeMotion.CrossingFailure
2541// grp.RootPart.Velocity = Vector3.Zero;
2542 grp.RootPart.KeyframeMotion.CrossingFailure();
2543// grp.SendGroupRootTerseUpdate();
2544 }
2545 }
2546 }
2547
2548 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
2549 }
2550 */
2551 } 2527 }
2552 else 2528 else
2553 { 2529 {
@@ -2589,7 +2565,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2589 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", 2565 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}",
2590 clone.UUID, destination.RegionName); 2566 clone.UUID, destination.RegionName);
2591 2567
2592 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent); 2568 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent,true);
2593 } 2569 }
2594 } 2570 }
2595 2571
@@ -2639,7 +2615,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2639 if (Scene.RegionInfo.EstateSettings.IsBanned(so.OwnerID)) 2615 if (Scene.RegionInfo.EstateSettings.IsBanned(so.OwnerID))
2640 { 2616 {
2641 m_log.DebugFormat( 2617 m_log.DebugFormat(
2642 "[ENTITY TRANSFER MODULE]: Denied prim crossing of {0} {1} into {2} for banned avatar {3}", 2618 "[ENTITY TRANSFER MODULE]: Denied prim crossing of {0} {1} into {2} for banned avatar {3}",
2643 so.Name, so.UUID, Scene.Name, so.OwnerID); 2619 so.Name, so.UUID, Scene.Name, so.OwnerID);
2644 2620
2645 return false; 2621 return false;
@@ -2651,7 +2627,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2651 if (!Scene.AddSceneObject(so)) 2627 if (!Scene.AddSceneObject(so))
2652 { 2628 {
2653 m_log.DebugFormat( 2629 m_log.DebugFormat(
2654 "[ENTITY TRANSFER MODULE]: Problem adding scene object {0} {1} into {2} ", 2630 "[ENTITY TRANSFER MODULE]: Problem adding scene object {0} {1} into {2} ",
2655 so.Name, so.UUID, Scene.Name); 2631 so.Name, so.UUID, Scene.Name);
2656 2632
2657 return false; 2633 return false;
@@ -2661,7 +2637,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2661 { 2637 {
2662 // FIXME: It would be better to never add the scene object at all rather than add it and then delete 2638 // FIXME: It would be better to never add the scene object at all rather than add it and then delete
2663 // it 2639 // it
2664 if (!Scene.Permissions.CanObjectEntry(so.UUID, true, so.AbsolutePosition)) 2640 if (!Scene.Permissions.CanObjectEntry(so, true, so.AbsolutePosition))
2665 { 2641 {
2666 // Deny non attachments based on parcel settings 2642 // Deny non attachments based on parcel settings
2667 // 2643 //
@@ -2679,8 +2655,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2679 2655
2680 so.ResumeScripts(); 2656 so.ResumeScripts();
2681 2657
2682 if (so.RootPart.KeyframeMotion != null) 2658 // AddSceneObject already does this and doing it again messes
2683 so.RootPart.KeyframeMotion.UpdateSceneObject(so); 2659 //if (so.RootPart.KeyframeMotion != null)
2660 // so.RootPart.KeyframeMotion.UpdateSceneObject(so);
2684 } 2661 }
2685 2662
2686 return true; 2663 return true;
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index a3109e0..0a24555 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -101,7 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
101 /// <returns>true if the agent was not already in transit, false if it was</returns> 101 /// <returns>true if the agent was not already in transit, false if it was</returns>
102 internal bool SetInTransit(UUID id) 102 internal bool SetInTransit(UUID id)
103 { 103 {
104 m_log.DebugFormat("{0} SetInTransit. agent={1}, newState=Preparing", LogHeader, id); 104// m_log.DebugFormat("{0} SetInTransit. agent={1}, newState=Preparing", LogHeader, id);
105 lock (m_agentsInTransit) 105 lock (m_agentsInTransit)
106 { 106 {
107 if (!m_agentsInTransit.ContainsKey(id)) 107 if (!m_agentsInTransit.ContainsKey(id))
@@ -123,7 +123,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
123 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> 123 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
124 internal bool UpdateInTransit(UUID id, AgentTransferState newState) 124 internal bool UpdateInTransit(UUID id, AgentTransferState newState)
125 { 125 {
126 m_log.DebugFormat("{0} UpdateInTransit. agent={1}, newState={2}", LogHeader, id, newState); 126 // m_log.DebugFormat("{0} UpdateInTransit. agent={1}, newState={2}", LogHeader, id, newState);
127 127
128 bool transitionOkay = false; 128 bool transitionOkay = false;
129 129
@@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
169 } 169 }
170 else 170 else
171 { 171 {
172 if (newState == AgentTransferState.Cancelling 172 if (newState == AgentTransferState.Cancelling
173 && (oldState == AgentTransferState.Preparing || oldState == AgentTransferState.Transferring)) 173 && (oldState == AgentTransferState.Preparing || oldState == AgentTransferState.Transferring))
174 { 174 {
175 transitionOkay = true; 175 transitionOkay = true;
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
181 } 181 }
182 182
183 if (!transitionOkay) 183 if (!transitionOkay)
184 failureMessage 184 failureMessage
185 = string.Format( 185 = string.Format(
186 "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}", 186 "Agent with ID {0} is not allowed to move from old transit state {1} to new state {2} in {3}",
187 id, oldState, newState, m_mod.Scene.RegionInfo.RegionName); 187 id, oldState, newState, m_mod.Scene.RegionInfo.RegionName);
@@ -192,7 +192,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
192 m_agentsInTransit[id] = newState; 192 m_agentsInTransit[id] = newState;
193 193
194// m_log.DebugFormat( 194// m_log.DebugFormat(
195// "[ENTITY TRANSFER STATE MACHINE]: Changed agent with id {0} from state {1} to {2} in {3}", 195// "[ENTITY TRANSFER STATE MACHINE]: Changed agent with id {0} from state {1} to {2} in {3}",
196// id, oldState, newState, m_mod.Scene.Name); 196// id, oldState, newState, m_mod.Scene.Name);
197 } 197 }
198 else if (failIfNotOkay) 198 else if (failIfNotOkay)
@@ -204,11 +204,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
204// { 204// {
205// if (oldState != null) 205// if (oldState != null)
206// m_log.DebugFormat( 206// m_log.DebugFormat(
207// "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} from state {1} to {2} in {3}", 207// "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} from state {1} to {2} in {3}",
208// id, oldState, newState, m_mod.Scene.Name); 208// id, oldState, newState, m_mod.Scene.Name);
209// else 209// else
210// m_log.DebugFormat( 210// m_log.DebugFormat(
211// "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} to state {1} in {2} since agent not in transit", 211// "[ENTITY TRANSFER STATE MACHINE]: Ignored change of agent with id {0} to state {1} in {2} since agent not in transit",
212// id, newState, m_mod.Scene.Name); 212// id, newState, m_mod.Scene.Name);
213// } 213// }
214 } 214 }
@@ -247,32 +247,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
247 { 247 {
248 AgentTransferState state = m_agentsInTransit[id]; 248 AgentTransferState state = m_agentsInTransit[id];
249 249
250 if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination) 250// if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination)
251 { 251// {
252 // FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed 252 // FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed
253 // to be handled properly - ResetFromTransit() could be invoked at any step along the process 253 // to be handled properly - ResetFromTransit() could be invoked at any step along the process
254 m_log.WarnFormat( 254// m_log.WarnFormat(
255 "[ENTITY TRANSFER STATE MACHINE]: Agent with ID {0} should not exit directly from state {1}, should go to {2} state first in {3}", 255// "[ENTITY TRANSFER STATE MACHINE]: Agent with ID {0} should not exit directly from state {1}, should go to {2} state first in {3}",
256 id, state, AgentTransferState.CleaningUp, m_mod.Scene.RegionInfo.RegionName); 256// id, state, AgentTransferState.CleaningUp, m_mod.Scene.RegionInfo.RegionName);
257 257
258// throw new Exception( 258// throw new Exception(
259// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first", 259// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first",
260// state, AgentTransferState.CleaningUp); 260// state, AgentTransferState.CleaningUp);
261 } 261// }
262 262
263 m_agentsInTransit.Remove(id); 263 m_agentsInTransit.Remove(id);
264 264
265 m_log.DebugFormat( 265// m_log.DebugFormat(
266 "[ENTITY TRANSFER STATE MACHINE]: Agent {0} cleared from transit in {1}", 266// "[ENTITY TRANSFER STATE MACHINE]: Agent {0} cleared from transit in {1}",
267 id, m_mod.Scene.RegionInfo.RegionName); 267// id, m_mod.Scene.RegionInfo.RegionName);
268 268
269 return true; 269 return true;
270 } 270 }
271 } 271 }
272 272
273 m_log.WarnFormat( 273// m_log.WarnFormat(
274 "[ENTITY TRANSFER STATE MACHINE]: Agent {0} requested to clear from transit in {1} but was already cleared", 274// "[ENTITY TRANSFER STATE MACHINE]: Agent {0} requested to clear from transit in {1} but was already cleared",
275 id, m_mod.Scene.RegionInfo.RegionName); 275// id, m_mod.Scene.RegionInfo.RegionName);
276 276
277 return false; 277 return false;
278 } 278 }
@@ -281,7 +281,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
281 { 281 {
282 if (!m_mod.WaitForAgentArrivedAtDestination) 282 if (!m_mod.WaitForAgentArrivedAtDestination)
283 return true; 283 return true;
284 284
285 lock (m_agentsInTransit) 285 lock (m_agentsInTransit)
286 { 286 {
287 AgentTransferState? currentState = GetAgentTransferState(id); 287 AgentTransferState? currentState = GetAgentTransferState(id);
@@ -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..56c654f 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -95,8 +95,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
95 95
96 foreach (AvatarAttachment att in a.GetAttachments()) 96 foreach (AvatarAttachment att in a.GetAttachments())
97 { 97 {
98 InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID); 98 InventoryItemBase item = Scene.InventoryService.GetItem(account.PrincipalID, att.ItemID);
99 item = Scene.InventoryService.GetItem(item);
100 if (item != null) 99 if (item != null)
101 a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID); 100 a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID);
102 else 101 else
@@ -161,10 +160,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
161 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); 160 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
162 //scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; 161 //scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject;
163 162
164 m_incomingSceneObjectEngine 163 m_incomingSceneObjectEngine
165 = new JobEngine( 164 = new JobEngine(
166 string.Format("HG Incoming Scene Object Engine ({0})", scene.Name), 165 string.Format("HG Incoming Scene Object Engine ({0})", scene.Name),
167 "HG INCOMING SCENE OBJECT ENGINE"); 166 "HG INCOMING SCENE OBJECT ENGINE", 30000);
168 167
169 StatsManager.RegisterStat( 168 StatsManager.RegisterStat(
170 new Stat( 169 new Stat(
@@ -239,13 +238,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
239 return region; 238 return region;
240 } 239 }
241 240
242 protected override bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 241 protected override bool NeedsClosing(GridRegion reg, bool OutViewRange)
243 { 242 {
244 if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 243 if (OutViewRange)
245 return true; 244 return true;
246 245
247 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 246 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) 247 if (flags == -1 || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
249 return true; 248 return true;
250 249
251 return false; 250 return false;
@@ -263,7 +262,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
263 } 262 }
264 } 263 }
265 264
266 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 265 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
267 { 266 {
268 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI); 267 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI);
269 reason = string.Empty; 268 reason = string.Empty;
@@ -273,7 +272,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
273 { 272 {
274 // this user is going to another grid 273 // this user is going to another grid
275 // for local users, check if HyperGrid teleport is allowed, based on user level 274 // for local users, check if HyperGrid teleport is allowed, based on user level
276 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport) 275 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.GodController.UserLevel < m_levelHGTeleport)
277 { 276 {
278 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); 277 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel.");
279 reason = "Hypergrid teleport not allowed"; 278 reason = "Hypergrid teleport not allowed";
@@ -292,7 +291,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
292 291
293 GridRegion source = new GridRegion(Scene.RegionInfo); 292 GridRegion source = new GridRegion(Scene.RegionInfo);
294 source.RawServerURI = m_GatekeeperURI; 293 source.RawServerURI = m_GatekeeperURI;
295 294
296 bool success = connector.LoginAgentToGrid(source, agentCircuit, reg, finalDestination, false, out reason); 295 bool success = connector.LoginAgentToGrid(source, agentCircuit, reg, finalDestination, false, out reason);
297 logout = success; // flag for later logout from this grid; this is an HG TP 296 logout = success; // flag for later logout from this grid; this is an HG TP
298 297
@@ -308,7 +307,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
308 } 307 }
309 } 308 }
310 309
311 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout); 310 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout);
311 }
312
313 public override void TriggerTeleportHome(UUID id, IClientAPI client)
314 {
315 TeleportHome(id, client);
312 } 316 }
313 317
314 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) 318 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
@@ -328,7 +332,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
328 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance"); 332 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance");
329 333
330 // Check wearables 334 // Check wearables
331 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 335 for (int i = 0; i < sp.Appearance.Wearables.Length ; i++)
332 { 336 {
333 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++) 337 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++)
334 { 338 {
@@ -337,13 +341,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
337 341
338 bool found = false; 342 bool found = false;
339 foreach (AvatarAppearance a in ExportedAppearance) 343 foreach (AvatarAppearance a in ExportedAppearance)
340 if (a.Wearables[i] != null) 344 if (i < a.Wearables.Length && a.Wearables[i] != null)
341 { 345 {
342 found = true; 346 found = true;
343 break; 347 break;
344 } 348 }
345 349
346 if (!found) 350 if (!found)
347 { 351 {
348 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); 352 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
349 return false; 353 return false;
@@ -351,7 +355,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
351 355
352 found = false; 356 found = false;
353 foreach (AvatarAppearance a in ExportedAppearance) 357 foreach (AvatarAppearance a in ExportedAppearance)
354 if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID) 358 if (i < a.Wearables.Length && sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID)
355 { 359 {
356 found = true; 360 found = true;
357 break; 361 break;
@@ -412,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
412 // // Rez needed npc attachments 416 // // Rez needed npc attachments
413 // Scene.AttachmentsModule.RezAttachments(sp); 417 // Scene.AttachmentsModule.RezAttachments(sp);
414 418
415 419
416 // IAvatarFactoryModule module = Scene.RequestModuleInterface<IAvatarFactoryModule>(); 420 // IAvatarFactoryModule module = Scene.RequestModuleInterface<IAvatarFactoryModule>();
417 // //module.SendAppearance(sp.UUID); 421 // //module.SendAppearance(sp.UUID);
418 // module.RequestRebake(sp, false); 422 // module.RequestRebake(sp, false);
@@ -429,11 +433,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
429 // return base.UpdateAgent(reg, finalDestination, agentData, sp); 433 // return base.UpdateAgent(reg, finalDestination, agentData, sp);
430 //} 434 //}
431 435
432 public override void TriggerTeleportHome(UUID id, IClientAPI client) 436
433 {
434 TeleportHome(id, client);
435 }
436
437 public override bool TeleportHome(UUID id, IClientAPI client) 437 public override bool TeleportHome(UUID id, IClientAPI client)
438 { 438 {
439 m_log.DebugFormat( 439 m_log.DebugFormat(
@@ -449,7 +449,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
449 } 449 }
450 450
451 // Foreign user wants to go home 451 // Foreign user wants to go home
452 // 452 //
453 AgentCircuitData aCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); 453 AgentCircuitData aCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
454 if (aCircuit == null || (aCircuit != null && !aCircuit.ServiceURLs.ContainsKey("HomeURI"))) 454 if (aCircuit == null || (aCircuit != null && !aCircuit.ServiceURLs.ContainsKey("HomeURI")))
455 { 455 {
@@ -470,7 +470,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
470 { 470 {
471 m_log.Debug("[HG ENTITY TRANSFER MODULE]: GetHomeRegion call failed ", e); 471 m_log.Debug("[HG ENTITY TRANSFER MODULE]: GetHomeRegion call failed ", e);
472 } 472 }
473 473
474 if (finalDestination == null) 474 if (finalDestination == null)
475 { 475 {
476 client.SendTeleportFailed("Your home region could not be found"); 476 client.SendTeleportFailed("Your home region could not be found");
@@ -487,13 +487,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
487 } 487 }
488 488
489 GridRegion homeGatekeeper = MakeRegion(aCircuit); 489 GridRegion homeGatekeeper = MakeRegion(aCircuit);
490 490
491 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}", 491 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); 492 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName);
493 493
494 DoTeleport( 494 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; 495 return true;
498 } 496 }
499 497
@@ -505,7 +503,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
505 /// <param name="position"></param> 503 /// <param name="position"></param>
506 public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) 504 public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
507 { 505 {
508 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}", 506 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}",
509 (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position); 507 (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position);
510 508
511 if (lm.Gatekeeper == string.Empty) 509 if (lm.Gatekeeper == string.Empty)
@@ -523,7 +521,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
523 remoteClient, info.RegionHandle, lm.Position, 521 remoteClient, info.RegionHandle, lm.Position,
524 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); 522 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
525 } 523 }
526 else 524 else
527 { 525 {
528 // Foreign region 526 // Foreign region
529 GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); 527 GatekeeperServiceConnector gConn = new GatekeeperServiceConnector();
@@ -583,7 +581,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
583 jobsRemoved, commonIdToRemove, jobsToReinsert.Count); 581 jobsRemoved, commonIdToRemove, jobsToReinsert.Count);
584 582
585 if (jobsToReinsert.Count > 0) 583 if (jobsToReinsert.Count > 0)
586 { 584 {
587 foreach (JobEngine.Job jobToReinsert in jobsToReinsert) 585 foreach (JobEngine.Job jobToReinsert in jobsToReinsert)
588 m_incomingSceneObjectEngine.QueueJob(jobToReinsert); 586 m_incomingSceneObjectEngine.QueueJob(jobToReinsert);
589 } 587 }
@@ -613,16 +611,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
613 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 611 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
614 { 612 {
615 m_incomingSceneObjectEngine.QueueJob( 613 m_incomingSceneObjectEngine.QueueJob(
616 string.Format("HG UUID Gather for attachment {0} for {1}", so.Name, aCircuit.Name), 614 string.Format("HG UUID Gather for attachment {0} for {1}", so.Name, aCircuit.Name),
617 () => 615 () =>
618 { 616 {
619 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 617 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
620 // m_log.DebugFormat( 618 // m_log.DebugFormat(
621 // "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset service {2}", 619 // "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset service {2}",
622 // so.Name, so.AttachedAvatar, url); 620 // so.Name, so.AttachedAvatar, url);
623 621
624 IDictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>(); 622 IDictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
625 HGUuidGatherer uuidGatherer 623 HGUuidGatherer uuidGatherer
626 = new HGUuidGatherer(Scene.AssetService, url, ids); 624 = new HGUuidGatherer(Scene.AssetService, url, ids);
627 uuidGatherer.AddForInspection(so); 625 uuidGatherer.AddForInspection(so);
628 626
@@ -648,7 +646,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
648 RemoveIncomingSceneObjectJobs(so.OwnerID.ToString()); 646 RemoveIncomingSceneObjectJobs(so.OwnerID.ToString());
649 647
650 return; 648 return;
651 } 649 }
652 } 650 }
653 651
654 // m_log.DebugFormat( 652 // m_log.DebugFormat(
@@ -659,7 +657,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
659 { 657 {
660 int tickStart = Util.EnvironmentTickCount(); 658 int tickStart = Util.EnvironmentTickCount();
661 659
662 uuidGatherer.FetchAsset(kvp.Key); 660 uuidGatherer.FetchAsset(kvp.Key);
663 661
664 int ticksElapsed = Util.EnvironmentTickCountSubtract(tickStart); 662 int ticksElapsed = Util.EnvironmentTickCountSubtract(tickStart);
665 663
@@ -672,15 +670,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
672 RemoveIncomingSceneObjectJobs(so.OwnerID.ToString()); 670 RemoveIncomingSceneObjectJobs(so.OwnerID.ToString());
673 671
674 return; 672 return;
675 } 673 }
676 } 674 }
677 675
678 base.HandleIncomingSceneObject(so, newPosition); 676 base.HandleIncomingSceneObject(so, newPosition);
679 677
680 // m_log.DebugFormat( 678 // m_log.DebugFormat(
681 // "[HG ENTITY TRANSFER MODULE]: Completed incoming attachment {0} for HG user {1} with asset server {2}", 679 // "[HG ENTITY TRANSFER MODULE]: Completed incoming attachment {0} for HG user {1} with asset server {2}",
682 // so.Name, so.OwnerID, url); 680 // so.Name, so.OwnerID, url);
683 }, 681 },
684 so.OwnerID.ToString()); 682 so.OwnerID.ToString());
685 } 683 }
686 } 684 }
@@ -700,7 +698,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
700 string url = aCircuit.ServiceURLs["HomeURI"].ToString(); 698 string url = aCircuit.ServiceURLs["HomeURI"].ToString();
701 IUserAgentService security = new UserAgentServiceConnector(url); 699 IUserAgentService security = new UserAgentServiceConnector(url);
702 return security.VerifyClient(aCircuit.SessionID, token); 700 return security.VerifyClient(aCircuit.SessionID, token);
703 } 701 }
704 else 702 else
705 { 703 {
706 m_log.DebugFormat( 704 m_log.DebugFormat(
@@ -748,7 +746,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
748 GridRegion region = new GridRegion(); 746 GridRegion region = new GridRegion();
749 747
750 Uri uri = null; 748 Uri uri = null;
751 if (!aCircuit.ServiceURLs.ContainsKey("HomeURI") || 749 if (!aCircuit.ServiceURLs.ContainsKey("HomeURI") ||
752 (aCircuit.ServiceURLs.ContainsKey("HomeURI") && !Uri.TryCreate(aCircuit.ServiceURLs["HomeURI"].ToString(), UriKind.Absolute, out uri))) 750 (aCircuit.ServiceURLs.ContainsKey("HomeURI") && !Uri.TryCreate(aCircuit.ServiceURLs["HomeURI"].ToString(), UriKind.Absolute, out uri)))
753 return null; 751 return null;
754 752
@@ -760,4 +758,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
760 return region; 758 return region;
761 } 759 }
762 } 760 }
763} \ No newline at end of file 761}
diff --git a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs
index b5a4005..63dbb19 100644
--- a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs
+++ b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs
@@ -41,34 +41,34 @@ namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander
41 public class Commander : ICommander 41 public class Commander : ICommander
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 /// <value> 45 /// <value>
46 /// Used in runtime class generation 46 /// Used in runtime class generation
47 /// </summary> 47 /// </summary>
48 private string m_generatedApiClassName; 48 private string m_generatedApiClassName;
49 49
50 public string Name 50 public string Name
51 { 51 {
52 get { return m_name; } 52 get { return m_name; }
53 } 53 }
54 private string m_name; 54 private string m_name;
55 55
56 public string Help 56 public string Help
57 { 57 {
58 get 58 get
59 { 59 {
60 StringBuilder sb = new StringBuilder(); 60 StringBuilder sb = new StringBuilder();
61 61
62 sb.AppendLine("=== " + m_name + " ==="); 62 sb.AppendLine("=== " + m_name + " ===");
63 63
64 foreach (ICommand com in m_commands.Values) 64 foreach (ICommand com in m_commands.Values)
65 { 65 {
66 sb.AppendLine("* " + Name + " " + com.Name + " - " + com.Help); 66 sb.AppendLine("* " + Name + " " + com.Name + " - " + com.Help);
67 } 67 }
68 68
69 return sb.ToString(); 69 return sb.ToString();
70 } 70 }
71 } 71 }
72 72
73 /// <summary> 73 /// <summary>
74 /// Constructor 74 /// Constructor
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander
78 { 78 {
79 m_name = name; 79 m_name = name;
80 m_generatedApiClassName = m_name[0].ToString().ToUpper(); 80 m_generatedApiClassName = m_name[0].ToString().ToUpper();
81 81
82 if (m_name.Length > 1) 82 if (m_name.Length > 1)
83 m_generatedApiClassName += m_name.Substring(1); 83 m_generatedApiClassName += m_name.Substring(1);
84 } 84 }
@@ -87,7 +87,7 @@ namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander
87 { 87 {
88 get { return m_commands; } 88 get { return m_commands; }
89 } 89 }
90 private Dictionary<string, ICommand> m_commands = new Dictionary<string, ICommand>(); 90 private Dictionary<string, ICommand> m_commands = new Dictionary<string, ICommand>();
91 91
92 #region ICommander Members 92 #region ICommander Members
93 93
@@ -162,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander
162 { 162 {
163 if (function != "help") 163 if (function != "help")
164 Console.WriteLine("ERROR: Invalid command - No such command exists"); 164 Console.WriteLine("ERROR: Invalid command - No such command exists");
165 165
166 Console.Write(Help); 166 Console.Write(Help);
167 } 167 }
168 } 168 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index f54298c..51ae217 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
178 { 178 {
179 UUID uuid = UUID.Zero; 179 UUID uuid = UUID.Zero;
180 UUID.TryParse(meta.CreatorID, out uuid); 180 UUID.TryParse(meta.CreatorID, out uuid);
181 UserAccount creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); 181 UserAccount creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
182 if (creator != null) 182 if (creator != null)
183 meta.CreatorID = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName; 183 meta.CreatorID = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName;
184 } 184 }
@@ -300,8 +300,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
300 { 300 {
301 m_log.Error( 301 m_log.Error(
302 string.Format( 302 string.Format(
303 "[HG ASSET MAPPER]: Failed to post asset {0} (type {1}, length {2}) referenced from {3} to {4} with exception ", 303 "[HG ASSET MAPPER]: Failed to post asset {0} (type {1}, length {2}) referenced from {3} to {4} with exception ",
304 asset.ID, asset.Type, asset.Data.Length, assetID, userAssetURL), 304 asset.ID, asset.Type, asset.Data.Length, assetID, userAssetURL),
305 e); 305 e);
306 306
307 // For debugging purposes for now we will continue to throw the exception up the stack as was already happening. However, after 307 // For debugging purposes for now we will continue to throw the exception up the stack as was already happening. However, after
@@ -315,7 +315,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
315 else 315 else
316 { 316 {
317 m_log.DebugFormat( 317 m_log.DebugFormat(
318 "[HG ASSET MAPPER]: Didn't post asset {0} referenced from {1} because it already exists in asset server {2}", 318 "[HG ASSET MAPPER]: Didn't post asset {0} referenced from {1} because it already exists in asset server {2}",
319 uuid, assetID, userAssetURL); 319 uuid, assetID, userAssetURL);
320 } 320 }
321 } 321 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 582b267..8f6eca6 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -91,9 +91,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
91 if (name == Name) 91 if (name == Name)
92 { 92 {
93 m_Enabled = true; 93 m_Enabled = true;
94 94
95 InitialiseCommon(source); 95 InitialiseCommon(source);
96 96
97 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name); 97 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name);
98 98
99 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; 99 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
@@ -103,8 +103,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
103 new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty); 103 new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty);
104 m_ThisGatekeeper = Util.GetConfigVarFromSections<string>(source, "GatekeeperURI", 104 m_ThisGatekeeper = Util.GetConfigVarFromSections<string>(source, "GatekeeperURI",
105 new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty); 105 new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty);
106 // Legacy. Renove soon! 106 // Legacy. Remove soon!
107 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", m_ThisGatekeeper); 107//// m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", m_ThisGatekeeper);
108 108
109 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); 109 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
110 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); 110 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true);
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
117 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 117 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
118 118
119 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(source, "serverside_object_permissions", 119 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(source, "serverside_object_permissions",
120 new string[] { "Startup", "Permissions" }, true); 120 new string[] { "Startup", "Permissions" }, true);
121 121
122 } 122 }
123 } 123 }
@@ -209,7 +209,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
209 } 209 }
210 } 210 }
211 211
212 public void PostInventoryAsset(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel) 212 private void PostInventoryAsset(InventoryItemBase item, int userlevel)
213 {
214 InventoryFolderBase f = m_Scene.InventoryService.GetFolderForType(item.Owner, FolderType.Trash);
215 if (f == null || (f != null && item.Folder != f.ID))
216 PostInventoryAsset(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
217 }
218
219 private void PostInventoryAsset(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel)
213 { 220 {
214 if (type == AssetType.Link) 221 if (type == AssetType.Link)
215 return; 222 return;
@@ -241,26 +248,34 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
241 } 248 }
242 249
243 250
244 /// 251 ///
245 /// CapsUpdateInventoryItemAsset 252 /// CapsUpdateInventoryItemAsset
246 /// 253 ///
247 public override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data) 254 public override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
248 { 255 {
249 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data); 256 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
250 257
251 PostInventoryAsset(remoteClient.AgentId, AssetType.Unknown, newAssetID, "", 0); 258 // We need to construct this here to satisfy the calling convention.
259 // Better this in two places than five formal params in all others.
260 InventoryItemBase item = new InventoryItemBase();
261 item.Owner = remoteClient.AgentId;
262 item.AssetType = (int)AssetType.Unknown;
263 item.AssetID = newAssetID;
264 item.Name = String.Empty;
265
266 PostInventoryAsset(item, 0);
252 267
253 return newAssetID; 268 return newAssetID;
254 } 269 }
255 270
256 /// 271 ///
257 /// UpdateInventoryItemAsset 272 /// UpdateInventoryItemAsset
258 /// 273 ///
259 public override bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset) 274 public override bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset)
260 { 275 {
261 if (base.UpdateInventoryItemAsset(ownerID, item, asset)) 276 if (base.UpdateInventoryItemAsset(ownerID, item, asset))
262 { 277 {
263 PostInventoryAsset(ownerID, (AssetType)asset.Type, asset.FullID, asset.Name, 0); 278 PostInventoryAsset(item, 0);
264 return true; 279 return true;
265 } 280 }
266 281
@@ -273,25 +288,45 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
273 protected override void ExportAsset(UUID agentID, UUID assetID) 288 protected override void ExportAsset(UUID agentID, UUID assetID)
274 { 289 {
275 if (!assetID.Equals(UUID.Zero)) 290 if (!assetID.Equals(UUID.Zero))
276 PostInventoryAsset(agentID, AssetType.Unknown, assetID, "", 0); 291 {
292 InventoryItemBase item = new InventoryItemBase();
293 item.Owner = agentID;
294 item.AssetType = (int)AssetType.Unknown;
295 item.AssetID = assetID;
296 item.Name = String.Empty;
297
298 PostInventoryAsset(item, 0);
299 }
277 else 300 else
301 {
278 m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); 302 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
303 }
279 } 304 }
280 305
281 /// 306 ///
282 /// RezObject 307 /// RezObject
283 /// 308 ///
284 public override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, 309 // compatibility do not use
285 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 310 public override SceneObjectGroup RezObject(
286 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 311 IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
312 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
313 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
314 {
315 return RezObject(remoteClient, itemID, UUID.Zero, RayEnd, RayStart,
316 RayTargetID, BypassRayCast, RayEndIsIntersection,
317 RezSelected, RemoveItem, fromTaskID, attachment);
318 }
319
320 public override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID,
321 UUID groupID, Vector3 RayEnd, Vector3 RayStart,
322 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
323 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
287 { 324 {
288 m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); 325 //m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
289 326
290 //if (fromTaskID.Equals(UUID.Zero)) 327 //if (fromTaskID.Equals(UUID.Zero))
291 //{ 328 //{
292 InventoryItemBase item = new InventoryItemBase(itemID); 329 InventoryItemBase item = m_Scene.InventoryService.GetItem(remoteClient.AgentId, itemID);
293 item.Owner = remoteClient.AgentId;
294 item = m_Scene.InventoryService.GetItem(item);
295 //if (item == null) 330 //if (item == null)
296 //{ // Fetch the item 331 //{ // Fetch the item
297 // item = new InventoryItemBase(); 332 // item = new InventoryItemBase();
@@ -308,7 +343,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
308 //} 343 //}
309 344
310 // OK, we're done fetching. Pass it up to the default RezObject 345 // OK, we're done fetching. Pass it up to the default RezObject
311 SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 346 SceneObjectGroup sog = base.RezObject(remoteClient, itemID, groupID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
312 RezSelected, RemoveItem, fromTaskID, attachment); 347 RezSelected, RemoveItem, fromTaskID, attachment);
313 348
314 return sog; 349 return sog;
@@ -351,7 +386,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
351 if (!m_CheckSeparateAssets) 386 if (!m_CheckSeparateAssets)
352 { 387 {
353 if (!UserManagementModule.IsLocalGridUser(userID)) 388 if (!UserManagementModule.IsLocalGridUser(userID))
354 { // foreign 389 { // foreign
355 ScenePresence sp = null; 390 ScenePresence sp = null;
356 if (m_Scene.TryGetScenePresence(userID, out sp)) 391 if (m_Scene.TryGetScenePresence(userID, out sp))
357 { 392 {
@@ -489,7 +524,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
489 foreach (InventoryItemBase it in content.Items) 524 foreach (InventoryItemBase it in content.Items)
490 it.Name = it.Name + " (Unavailable)"; ; 525 it.Name = it.Name + " (Unavailable)"; ;
491 526
492 // Send the new names 527 // Send the new names
493 inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); 528 inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray());
494 529
495 } 530 }
@@ -506,16 +541,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
506 541
507 #region Permissions 542 #region Permissions
508 543
509 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) 544 private bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp)
510 { 545 {
511 if (m_bypassPermissions) return true; 546 if (m_bypassPermissions) return true;
512 547
513 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer)) 548 if(sp == null || sog == null)
549 return false;
550
551 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(sp.UUID))
514 { 552 {
515 SceneObjectGroup sog = null; 553 if (sog.OwnerID == sp.UUID)
516 if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer)
517 return true; 554 return true;
518
519 return false; 555 return false;
520 } 556 }
521 557
@@ -535,4 +571,4 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
535 571
536 #endregion 572 #endregion
537 } 573 }
538} \ No newline at end of file 574}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 5a9efb8..788ed1c 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
68 return m_UserManagement; 68 return m_UserManagement;
69 } 69 }
70 } 70 }
71 71
72 public bool CoalesceMultipleObjectsToInventory { get; set; } 72 public bool CoalesceMultipleObjectsToInventory { get; set; }
73 73
74 #region INonSharedRegionModule 74 #region INonSharedRegionModule
@@ -92,14 +92,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
92 if (name == Name) 92 if (name == Name)
93 { 93 {
94 m_Enabled = true; 94 m_Enabled = true;
95 95
96 InitialiseCommon(source); 96 InitialiseCommon(source);
97 97
98 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name); 98 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name);
99 } 99 }
100 } 100 }
101 } 101 }
102 102
103 /// <summary> 103 /// <summary>
104 /// Common module config for both this and descendant classes. 104 /// Common module config for both this and descendant classes.
105 /// </summary> 105 /// </summary>
@@ -107,9 +107,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
107 protected virtual void InitialiseCommon(IConfigSource source) 107 protected virtual void InitialiseCommon(IConfigSource source)
108 { 108 {
109 IConfig inventoryConfig = source.Configs["Inventory"]; 109 IConfig inventoryConfig = source.Configs["Inventory"];
110 110
111 if (inventoryConfig != null) 111 if (inventoryConfig != null)
112 CoalesceMultipleObjectsToInventory 112 CoalesceMultipleObjectsToInventory
113 = inventoryConfig.GetBoolean("CoalesceMultipleObjectsToInventory", true); 113 = inventoryConfig.GetBoolean("CoalesceMultipleObjectsToInventory", true);
114 else 114 else
115 CoalesceMultipleObjectsToInventory = true; 115 CoalesceMultipleObjectsToInventory = true;
@@ -175,53 +175,73 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
175 /// <param name="nextOwnerMask"></param> 175 /// <param name="nextOwnerMask"></param>
176 public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, 176 public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID,
177 uint callbackID, string description, string name, sbyte invType, 177 uint callbackID, string description, string name, sbyte invType,
178 sbyte assetType, 178 sbyte assetType, byte wearableType,
179 byte wearableType, uint nextOwnerMask, int creationDate) 179 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 folder = m_Scene.InventoryService.GetFolder(remoteClient.AgentId, folderID);
188
189 if (folder == null && Enum.IsDefined(typeof(FolderType), (sbyte)invType))
187 { 190 {
188 ScenePresence presence; 191 folder = m_Scene.InventoryService.GetFolderForType(remoteClient.AgentId, (FolderType)invType);
189 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 192 if (folder != null)
190 { 193 m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Requested folder not found but found folder for type {0}", invType);
191 byte[] data = null; 194 }
192 195
193 if (invType == (sbyte)InventoryType.Landmark && presence != null) 196 if (folder == null || folder.Owner != remoteClient.AgentId)
194 { 197 return;
195 string suffix = string.Empty, prefix = string.Empty;
196 string strdata = GenerateLandmark(presence, out prefix, out suffix);
197 data = Encoding.ASCII.GetBytes(strdata);
198 name = prefix + name;
199 description += suffix;
200 }
201 198
202 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); 199 if (transactionID != UUID.Zero)
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 {
210 m_log.ErrorFormat(
211 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
212 remoteClient.AgentId);
213 }
214 }
215 else
216 { 200 {
217 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; 201 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
218 if (agentTransactions != null) 202 if (agentTransactions != null)
219 { 203 {
220 agentTransactions.HandleItemCreationFromTransaction( 204 if (agentTransactions.HandleItemCreationFromTransaction(
221 remoteClient, transactionID, folderID, callbackID, description, 205 remoteClient, transactionID, folderID, callbackID, description,
222 name, invType, assetType, wearableType, nextOwnerMask); 206 name, invType, assetType, wearableType, nextOwnerMask))
207 return;
223 } 208 }
224 } 209 }
210
211 ScenePresence presence;
212 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
213 {
214 byte[] data = null;
215 uint everyonemask = 0;
216 uint groupmask = 0;
217
218 if (invType == (sbyte)InventoryType.Landmark && presence != null)
219 {
220 string suffix = string.Empty, prefix = string.Empty;
221 string strdata = GenerateLandmark(presence, out prefix, out suffix);
222 data = Encoding.ASCII.GetBytes(strdata);
223 name = prefix + name;
224 description += suffix;
225 groupmask = (uint)PermissionMask.AllAndExport;
226 everyonemask = (uint)(PermissionMask.AllAndExport & ~PermissionMask.Modify);
227 }
228
229 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
230 m_Scene.AssetService.Store(asset);
231 m_Scene.CreateNewInventoryItem(
232 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
233 name, description, 0, callbackID, asset.FullID, asset.Type, invType,
234 (uint)PermissionMask.AllAndExport, // Base
235 (uint)PermissionMask.AllAndExport, // Current
236 everyonemask,
237 nextOwnerMask, groupmask, creationDate, false); // Data from viewer
238 }
239 else
240 {
241 m_log.ErrorFormat(
242 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
243 remoteClient.AgentId);
244 }
225 } 245 }
226 246
227 protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) 247 protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
@@ -244,53 +264,65 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
244 /// <returns></returns> 264 /// <returns></returns>
245 public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data) 265 public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
246 { 266 {
247 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 267 InventoryItemBase item = m_Scene.InventoryService.GetItem(remoteClient.AgentId, itemID);
248 item = m_Scene.InventoryService.GetItem(item); 268
269 if (item == null)
270 {
271 m_log.ErrorFormat(
272 "[INVENTORY ACCESS MODULE]: Could not find item {0} for caps inventory update", itemID);
273 return UUID.Zero;
274 }
249 275
250 if (item.Owner != remoteClient.AgentId) 276 if (item.Owner != remoteClient.AgentId)
251 return UUID.Zero; 277 return UUID.Zero;
252 278
253 if (item != null) 279 if ((InventoryType)item.InvType == InventoryType.Notecard)
254 { 280 {
255 if ((InventoryType)item.InvType == InventoryType.Notecard) 281 if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId))
256 { 282 {
257 if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId)) 283 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
258 { 284 return UUID.Zero;
259 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
260 return UUID.Zero;
261 }
262
263 remoteClient.SendAlertMessage("Notecard saved");
264 } 285 }
265 else if ((InventoryType)item.InvType == InventoryType.LSL)
266 {
267 if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
268 {
269 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
270 return UUID.Zero;
271 }
272 286
273 remoteClient.SendAlertMessage("Script saved"); 287 remoteClient.SendAlertMessage("Notecard saved");
288 }
289 else if ((InventoryType)item.InvType == InventoryType.LSL)
290 {
291 if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
292 {
293 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
294 return UUID.Zero;
274 } 295 }
275 296
276 AssetBase asset = 297 remoteClient.SendAlertMessage("Script saved");
277 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString());
278 item.AssetID = asset.FullID;
279 m_Scene.AssetService.Store(asset);
280
281 m_Scene.InventoryService.UpdateItem(item);
282
283 // remoteClient.SendInventoryItemCreateUpdate(item);
284 return (asset.FullID);
285 } 298 }
286 else 299 else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet)
287 { 300 {
288 m_log.ErrorFormat( 301 AnimationSet animSet = new AnimationSet(data);
289 "[INVENTORY ACCESS MODULE]: Could not find item {0} for caps inventory update", 302 uint res = animSet.Validate(x => {
290 itemID); 303 const int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
304 int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x);
305 // enforce previus perm rule
306 if ((perms & required) != required)
307 return 0;
308 return (uint) perms;
309 });
310 if(res == 0)
311 {
312 remoteClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false);
313 return UUID.Zero;
314 }
291 } 315 }
292 316
293 return UUID.Zero; 317 AssetBase asset =
318 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString());
319 item.AssetID = asset.FullID;
320 m_Scene.AssetService.Store(asset);
321
322 m_Scene.InventoryService.UpdateItem(item);
323
324 // remoteClient.SendInventoryItemCreateUpdate(item);
325 return (asset.FullID);
294 } 326 }
295 327
296 public virtual bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset) 328 public virtual bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset)
@@ -298,7 +330,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
298 if (item != null && item.Owner == ownerID && asset != null) 330 if (item != null && item.Owner == ownerID && asset != null)
299 { 331 {
300// m_log.DebugFormat( 332// m_log.DebugFormat(
301// "[INVENTORY ACCESS MODULE]: Updating item {0} {1} with new asset {2}", 333// "[INVENTORY ACCESS MODULE]: Updating item {0} {1} with new asset {2}",
302// item.Name, item.ID, asset.ID); 334// item.Name, item.ID, asset.ID);
303 335
304 item.AssetID = asset.FullID; 336 item.AssetID = asset.FullID;
@@ -327,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
327 List<InventoryItemBase> copiedItems = new List<InventoryItemBase>(); 359 List<InventoryItemBase> copiedItems = new List<InventoryItemBase>();
328 360
329 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>(); 361 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
330 362
331 if (CoalesceMultipleObjectsToInventory) 363 if (CoalesceMultipleObjectsToInventory)
332 { 364 {
333 // The following code groups the SOG's by owner. No objects 365 // The following code groups the SOG's by owner. No objects
@@ -337,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
337 { 369 {
338 if (!bundlesToCopy.ContainsKey(g.OwnerID)) 370 if (!bundlesToCopy.ContainsKey(g.OwnerID))
339 bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>(); 371 bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>();
340 372
341 bundlesToCopy[g.OwnerID].Add(g); 373 bundlesToCopy[g.OwnerID].Add(g);
342 } 374 }
343 } 375 }
@@ -348,7 +380,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
348 { 380 {
349 List<SceneObjectGroup> bundle = new List<SceneObjectGroup>(); 381 List<SceneObjectGroup> bundle = new List<SceneObjectGroup>();
350 bundle.Add(g); 382 bundle.Add(g);
351 bundlesToCopy[g.UUID] = bundle; 383 bundlesToCopy[g.UUID] = bundle;
352 } 384 }
353 } 385 }
354 386
@@ -360,10 +392,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
360 // with distinct destinations as well. 392 // with distinct destinations as well.
361 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values) 393 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
362 copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment)); 394 copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment));
363 395
364 return copiedItems; 396 return copiedItems;
365 } 397 }
366 398
367 /// <summary> 399 /// <summary>
368 /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object 400 /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object
369 /// item. If there are multiple objects then these will be saved as a single coalesced item. 401 /// item. If there are multiple objects then these will be saved as a single coalesced item.
@@ -379,33 +411,42 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
379 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient, 411 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient,
380 bool asAttachment) 412 bool asAttachment)
381 { 413 {
382 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 414 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
383// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 415 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
384 416 Dictionary<UUID, Quaternion> originalRotations = new Dictionary<UUID, Quaternion>();
385 Dictionary<SceneObjectGroup, KeyframeMotion> group2Keyframe = new Dictionary<SceneObjectGroup, KeyframeMotion>(); 417 // this possible is not needed if keyframes are saved
418// Dictionary<UUID, KeyframeMotion> originalKeyframes = new Dictionary<UUID, KeyframeMotion>();
386 419
387 foreach (SceneObjectGroup objectGroup in objlist) 420 foreach (SceneObjectGroup objectGroup in objlist)
388 { 421 {
389 if (objectGroup.RootPart.KeyframeMotion != null) 422 if (objectGroup.RootPart.KeyframeMotion != null)
390 { 423 {
391 objectGroup.RootPart.KeyframeMotion.Pause(); 424 objectGroup.RootPart.KeyframeMotion.Suspend();
392 group2Keyframe.Add(objectGroup, objectGroup.RootPart.KeyframeMotion);
393 objectGroup.RootPart.KeyframeMotion = null;
394 } 425 }
426 objectGroup.RootPart.SetForce(Vector3.Zero);
427 objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
395 428
396// Vector3 inventoryStoredPosition = new Vector3 429// originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion;
397// (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 430// objectGroup.RootPart.KeyframeMotion = null;
398// ? 250 431
399// : objectGroup.AbsolutePosition.X) 432 Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition;
400// , 433 originalPositions[objectGroup.UUID] = inventoryStoredPosition;
401// (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) 434 Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
402// ? 250 435 originalRotations[objectGroup.UUID] = inventoryStoredRotation;
403// : objectGroup.AbsolutePosition.Y, 436
404// objectGroup.AbsolutePosition.Z); 437 // Restore attachment data after trip through the sim
405// 438 if (objectGroup.AttachmentPoint > 0)
406// originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 439 {
407// 440 inventoryStoredPosition = objectGroup.RootPart.AttachedPos;
408// objectGroup.AbsolutePosition = inventoryStoredPosition; 441 inventoryStoredRotation = objectGroup.RootPart.AttachRotation;
442 if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree &&
443 objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree)
444 objectGroup.RootPart.Shape.LastAttachPoint = (byte)objectGroup.AttachmentPoint;
445
446 }
447
448 objectGroup.AbsolutePosition = inventoryStoredPosition;
449 objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
409 450
410 // Make sure all bits but the ones we want are clear 451 // Make sure all bits but the ones we want are clear
411 // on take. 452 // on take.
@@ -418,7 +459,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
418 (uint)PermissionMask.Export); 459 (uint)PermissionMask.Export);
419 objectGroup.RootPart.NextOwnerMask |= 460 objectGroup.RootPart.NextOwnerMask |=
420 (uint)PermissionMask.Move; 461 (uint)PermissionMask.Move;
421 462
422 coa.Add(objectGroup); 463 coa.Add(objectGroup);
423 } 464 }
424 465
@@ -432,10 +473,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
432 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment); 473 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment);
433 else 474 else
434 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); 475 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
435 476
436// // Restore the position of each group now that it has been stored to inventory. 477 // Restore the position of each group now that it has been stored to inventory.
437// foreach (SceneObjectGroup objectGroup in objlist) 478 foreach (SceneObjectGroup objectGroup in objlist)
438// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 479 {
480 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
481 objectGroup.RootPart.RotationOffset = originalRotations[objectGroup.UUID];
482// objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID];
483 if (objectGroup.RootPart.KeyframeMotion != null)
484 objectGroup.RootPart.KeyframeMotion.Resume();
485 }
439 486
440 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 487 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
441 488
@@ -448,11 +495,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
448 495
449 item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); 496 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
450 item.CreatorData = objlist[0].RootPart.CreatorData; 497 item.CreatorData = objlist[0].RootPart.CreatorData;
451 498
452 if (objlist.Count > 1) 499 if (objlist.Count > 1)
453 { 500 {
454 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; 501 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
455 502
456 // If the objects have different creators then don't specify a creator at all 503 // If the objects have different creators then don't specify a creator at all
457 foreach (SceneObjectGroup objectGroup in objlist) 504 foreach (SceneObjectGroup objectGroup in objlist)
458 { 505 {
@@ -468,8 +515,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
468 else 515 else
469 { 516 {
470 item.SaleType = objlist[0].RootPart.ObjectSaleType; 517 item.SaleType = objlist[0].RootPart.ObjectSaleType;
471 item.SalePrice = objlist[0].RootPart.SalePrice; 518 item.SalePrice = objlist[0].RootPart.SalePrice;
472 } 519 }
473 520
474 AssetBase asset = CreateAsset( 521 AssetBase asset = CreateAsset(
475 objlist[0].GetPartName(objlist[0].RootPart.LocalId), 522 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
@@ -478,7 +525,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
478 Utils.StringToBytes(itemXml), 525 Utils.StringToBytes(itemXml),
479 objlist[0].OwnerID.ToString()); 526 objlist[0].OwnerID.ToString());
480 m_Scene.AssetService.Store(asset); 527 m_Scene.AssetService.Store(asset);
481 528
482 item.AssetID = asset.FullID; 529 item.AssetID = asset.FullID;
483 530
484 if (DeRezAction.SaveToExistingUserInventoryItem == action) 531 if (DeRezAction.SaveToExistingUserInventoryItem == action)
@@ -487,13 +534,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
487 } 534 }
488 else 535 else
489 { 536 {
537 AddPermissions(item, objlist[0], objlist, remoteClient);
538
490 item.CreationDate = Util.UnixTimeSinceEpoch(); 539 item.CreationDate = Util.UnixTimeSinceEpoch();
491 item.Description = asset.Description; 540 item.Description = asset.Description;
492 item.Name = asset.Name; 541 item.Name = asset.Name;
493 item.AssetType = asset.Type; 542 item.AssetType = asset.Type;
494 543
495 AddPermissions(item, objlist[0], objlist, remoteClient);
496
497 m_Scene.AddInventoryItem(item); 544 m_Scene.AddInventoryItem(item);
498 545
499 if (remoteClient != null && item.Owner == remoteClient.AgentId) 546 if (remoteClient != null && item.Owner == remoteClient.AgentId)
@@ -510,17 +557,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
510 } 557 }
511 } 558 }
512 559
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 560 // This is a hook to do some per-asset post-processing for subclasses that need that
521 if (remoteClient != null) 561 if (remoteClient != null && action != DeRezAction.Delete)
522 ExportAsset(remoteClient.AgentId, asset.FullID); 562 ExportAsset(remoteClient.AgentId, asset.FullID);
523 563
524 return item; 564 return item;
525 } 565 }
526 566
@@ -538,56 +578,41 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
538 /// <param name="remoteClient"></param> 578 /// <param name="remoteClient"></param>
539 /// <returns></returns> 579 /// <returns></returns>
540 protected InventoryItemBase AddPermissions( 580 protected InventoryItemBase AddPermissions(
541 InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions, 581 InventoryItemBase item, SceneObjectGroup so, List<SceneObjectGroup> objsForEffectivePermissions,
542 IClientAPI remoteClient) 582 IClientAPI remoteClient)
543 { 583 {
544 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; 584 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export | PermissionMask.FoldedMask);
545 uint allObjectsNextOwnerPerms = 0x7fffffff; 585
546 uint allObjectsEveryOnePerms = 0x7fffffff;
547 uint allObjectsGroupPerms = 0x7fffffff;
548
549 foreach (SceneObjectGroup grp in objsForEffectivePermissions) 586 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
550 { 587 {
551 effectivePerms &= grp.GetEffectivePermissions(); 588 effectivePerms &= grp.CurrentAndFoldedNextPermissions();
552 allObjectsNextOwnerPerms &= grp.RootPart.NextOwnerMask;
553 allObjectsEveryOnePerms &= grp.RootPart.EveryoneMask;
554 allObjectsGroupPerms &= grp.RootPart.GroupMask;
555 } 589 }
556 effectivePerms |= (uint)PermissionMask.Move; 590
557
558 //PermissionsUtil.LogPermissions(item.Name, "Before AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
559
560 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 591 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
561 { 592 {
562 // Changing ownership, so apply the "Next Owner" permissions to all of the 593 // apply parts inventory items next owner
563 // inventory item's permissions. 594 PermissionsUtil.ApplyNoModFoldedPermissions(effectivePerms, ref effectivePerms);
564 595 // change to next owner
565 uint perms = effectivePerms; 596 uint basePerms = effectivePerms & so.RootPart.NextOwnerMask;
566 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms); 597 // fix and update folded
567 598 basePerms = PermissionsUtil.FixAndFoldPermissions(basePerms);
568 item.BasePermissions = perms & allObjectsNextOwnerPerms; 599
569 item.CurrentPermissions = item.BasePermissions; 600 item.BasePermissions = basePerms;
570 item.NextPermissions = perms & allObjectsNextOwnerPerms; 601 item.CurrentPermissions = basePerms;
571 item.EveryOnePermissions = allObjectsEveryOnePerms & allObjectsNextOwnerPerms; 602 item.NextPermissions = basePerms & so.RootPart.NextOwnerMask;
572 item.GroupPermissions = allObjectsGroupPerms & allObjectsNextOwnerPerms; 603 item.EveryOnePermissions = basePerms & so.RootPart.EveryoneMask;
573 604 item.GroupPermissions = basePerms & so.RootPart.GroupMask;
605
574 // apply next owner perms on rez 606 // apply next owner perms on rez
575 item.CurrentPermissions |= SceneObjectGroup.SLAM; 607 item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
576 } 608 }
577 else 609 else
578 { 610 {
579 // Not changing ownership.
580 // In this case we apply the permissions in the object's items ONLY to the inventory
581 // item's "Next Owner" permissions, but NOT to its "Current", "Base", etc. permissions.
582 // E.g., if the object contains a No-Transfer item then the item's "Next Owner"
583 // permissions are also No-Transfer.
584 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref allObjectsNextOwnerPerms);
585
586 item.BasePermissions = effectivePerms; 611 item.BasePermissions = effectivePerms;
587 item.CurrentPermissions = effectivePerms; 612 item.CurrentPermissions = effectivePerms;
588 item.NextPermissions = allObjectsNextOwnerPerms & effectivePerms; 613 item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
589 item.EveryOnePermissions = allObjectsEveryOnePerms & effectivePerms; 614 item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms;
590 item.GroupPermissions = allObjectsGroupPerms & effectivePerms; 615 item.GroupPermissions = so.RootPart.GroupMask & effectivePerms;
591 616
592 item.CurrentPermissions &= 617 item.CurrentPermissions &=
593 ((uint)PermissionMask.Copy | 618 ((uint)PermissionMask.Copy |
@@ -595,14 +620,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
595 (uint)PermissionMask.Modify | 620 (uint)PermissionMask.Modify |
596 (uint)PermissionMask.Move | 621 (uint)PermissionMask.Move |
597 (uint)PermissionMask.Export | 622 (uint)PermissionMask.Export |
598 7); // Preserve folded permissions 623 (uint)PermissionMask.FoldedMask); // Preserve folded permissions ??
599 } 624 }
600 625
601 //PermissionsUtil.LogPermissions(item.Name, "After AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
602
603 return item; 626 return item;
604 } 627 }
605 628
606 /// <summary> 629 /// <summary>
607 /// Create an item using details for the given scene object. 630 /// Create an item using details for the given scene object.
608 /// </summary> 631 /// </summary>
@@ -615,7 +638,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
615 DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID) 638 DeRezAction action, IClientAPI remoteClient, SceneObjectGroup so, UUID folderID)
616 { 639 {
617// m_log.DebugFormat( 640// m_log.DebugFormat(
618// "[BASIC INVENTORY ACCESS MODULE]: Creating item for object {0} {1} for folder {2}, action {3}", 641// "[BASIC INVENTORY ACCESS MODULE]: Creating item for object {0} {1} for folder {2}, action {3}",
619// so.Name, so.UUID, folderID, action); 642// so.Name, so.UUID, folderID, action);
620// 643//
621 // Get the user info of the item destination 644 // Get the user info of the item destination
@@ -663,14 +686,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
663 // Delete is treated like return in this case 686 // Delete is treated like return in this case
664 // Deleting your own items makes them go to trash 687 // Deleting your own items makes them go to trash
665 // 688 //
666 689
667 InventoryFolderBase folder = null; 690 InventoryFolderBase folder = null;
668 InventoryItemBase item = null; 691 InventoryItemBase item = null;
669 692
670 if (DeRezAction.SaveToExistingUserInventoryItem == action) 693 if (DeRezAction.SaveToExistingUserInventoryItem == action)
671 { 694 {
672 item = new InventoryItemBase(so.RootPart.FromUserInventoryItemID, userID); 695 item = m_Scene.InventoryService.GetItem(userID, so.RootPart.FromUserInventoryItemID);
673 item = m_Scene.InventoryService.GetItem(item);
674 696
675 //item = userInfo.RootFolder.FindItem( 697 //item = userInfo.RootFolder.FindItem(
676 // objectGroup.RootPart.FromUserInventoryItemID); 698 // objectGroup.RootPart.FromUserInventoryItemID);
@@ -680,7 +702,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
680 m_log.DebugFormat( 702 m_log.DebugFormat(
681 "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.", 703 "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.",
682 so.Name, so.UUID); 704 so.Name, so.UUID);
683 705
684 return null; 706 return null;
685 } 707 }
686 } 708 }
@@ -742,8 +764,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
742 { 764 {
743 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) 765 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
744 { 766 {
745 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 767 folder = m_Scene.InventoryService.GetFolder(userID, so.FromFolderID);
746 folder = m_Scene.InventoryService.GetFolder(f);
747 768
748 if(folder.Type == 14 || folder.Type == 16) 769 if(folder.Type == 14 || folder.Type == 16)
749 { 770 {
@@ -763,49 +784,65 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
763 } 784 }
764 } 785 }
765 786
766 item = new InventoryItemBase(); 787 item = new InventoryItemBase();
767 item.ID = UUID.Random(); 788 item.ID = UUID.Random();
768 item.InvType = (int)InventoryType.Object; 789 item.InvType = (int)InventoryType.Object;
769 item.Folder = folder.ID; 790 item.Folder = folder.ID;
770 item.Owner = userID; 791 item.Owner = userID;
771 } 792 }
772 793
773 return item; 794 return item;
774 } 795 }
775 796 // compatibility do not use
776 public virtual SceneObjectGroup RezObject( 797 public virtual SceneObjectGroup RezObject(
777 IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, 798 IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
778 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 799 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
779 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 800 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
780 { 801 {
781// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); 802 return RezObject(remoteClient, itemID, UUID.Zero, RayEnd, RayStart,
803 RayTargetID, BypassRayCast, RayEndIsIntersection,
804 RezSelected, RemoveItem, fromTaskID, attachment);
805 }
782 806
783 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 807 public virtual SceneObjectGroup RezObject(
784 item = m_Scene.InventoryService.GetItem(item); 808 IClientAPI remoteClient, UUID itemID, UUID rezGroupID, Vector3 RayEnd, Vector3 RayStart,
809 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
810 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
811 {
812// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
813 InventoryItemBase item = m_Scene.InventoryService.GetItem(remoteClient.AgentId, itemID);
785 814
786 if (item == null) 815 if (item == null)
787 { 816 {
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; 817 return null;
793 } 818 }
794 819
795 item.Owner = remoteClient.AgentId; 820 item.Owner = remoteClient.AgentId;
796 821
797 return RezObject( 822 return RezObject(
798 remoteClient, item, item.AssetID, 823 remoteClient, item, rezGroupID, item.AssetID,
799 RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 824 RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
800 RezSelected, RemoveItem, fromTaskID, attachment); 825 RezSelected, RemoveItem, fromTaskID, attachment);
801 } 826 }
802 827 // compatility
803 public virtual SceneObjectGroup RezObject( 828 public virtual SceneObjectGroup RezObject(
804 IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart, 829 IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart,
805 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 830 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
806 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 831 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
807 { 832 {
808 AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString()); 833 return RezObject(remoteClient, item, UUID.Zero, assetID,
834 RayEnd, RayStart, RayTargetID,
835 BypassRayCast, RayEndIsIntersection,
836 RezSelected, RemoveItem, fromTaskID, attachment);
837 }
838
839 public virtual SceneObjectGroup RezObject(
840 IClientAPI remoteClient, InventoryItemBase item, UUID groupID, UUID assetID,
841 Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID,
842 byte BypassRayCast, bool RayEndIsIntersection,
843 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
844 {
845 AssetBase rezAsset = m_Scene.AssetService.Get(assetID.ToString());
809 846
810 if (rezAsset == null) 847 if (rezAsset == null)
811 { 848 {
@@ -827,6 +864,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
827 return null; 864 return null;
828 } 865 }
829 866
867 if(rezAsset.Data == null || rezAsset.Data.Length == 0)
868 {
869 m_log.WarnFormat(
870 "[INVENTORY ACCESS MODULE]: missing data in asset {0} to RezObject()",
871 assetID, remoteClient.Name);
872 remoteClient.SendAgentAlertMessage(string.Format("Unable to rez: missing data in asset {0} ", assetID), false);
873 return null;
874 }
875
830 SceneObjectGroup group = null; 876 SceneObjectGroup group = null;
831 877
832 List<SceneObjectGroup> objlist; 878 List<SceneObjectGroup> objlist;
@@ -836,7 +882,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
836 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 882 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
837 Vector3 pos; 883 Vector3 pos;
838 884
839 bool single 885 bool single
840 = m_Scene.GetObjectsToRez( 886 = m_Scene.GetObjectsToRez(
841 rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight); 887 rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
842 888
@@ -856,12 +902,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
856 pos -= bbox / 2; 902 pos -= bbox / 2;
857 } 903 }
858 904
905 int primcount = 0;
906 foreach (SceneObjectGroup g in objlist)
907 primcount += g.PrimCount;
908
909 if (!m_Scene.Permissions.CanRezObject(
910 primcount, remoteClient.AgentId, pos)
911 && !attachment)
912 {
913 // The client operates in no fail mode. It will
914 // have already removed the item from the folder
915 // if it's no copy.
916 // Put it back if it's not an attachment
917 //
918 if (item != null)
919 {
920 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
921 remoteClient.SendBulkUpdateInventory(item);
922 }
923
924 return null;
925 }
926
859 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) 927 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
860 return null; 928 return null;
861 929
862 for (int i = 0; i < objlist.Count; i++) 930 for (int i = 0; i < objlist.Count; i++)
863 { 931 {
864 group = objlist[i]; 932 group = objlist[i];
933 SceneObjectPart rootPart = group.RootPart;
865 934
866// m_log.DebugFormat( 935// 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}", 936// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
@@ -891,9 +960,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
891 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. 960 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
892 part.LastOwnerID = part.OwnerID; 961 part.LastOwnerID = part.OwnerID;
893 part.OwnerID = remoteClient.AgentId; 962 part.OwnerID = remoteClient.AgentId;
963 part.RezzerID = remoteClient.AgentId;
894 } 964 }
895 } 965 }
896 966
967 group.ResetIDs();
968
897 if (!attachment) 969 if (!attachment)
898 { 970 {
899 // If it's rezzed in world, select it. Much easier to 971 // If it's rezzed in world, select it. Much easier to
@@ -903,48 +975,38 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
903 { 975 {
904 part.CreateSelected = true; 976 part.CreateSelected = true;
905 } 977 }
906 }
907 978
908 group.ResetIDs(); 979 if (rootPart.Shape.PCode == (byte)PCode.Prim)
909 980 group.ClearPartAttachmentData();
910 if (attachment) 981 }
982 else
911 { 983 {
912 group.RootPart.Flags |= PrimFlags.Phantom;
913 group.IsAttachment = true; 984 group.IsAttachment = true;
914 } 985 }
915 986
987 group.SetGroup(groupID, remoteClient);
988
916 // If we're rezzing an attachment then don't ask 989 // If we're rezzing an attachment then don't ask
917 // AddNewSceneObject() to update the client since 990 // AddNewSceneObject() to update the client since
918 // we'll be doing that later on. Scheduling more than 991 // we'll be doing that later on. Scheduling more than
919 // one full update during the attachment 992 // one full update during the attachment
920 // process causes some clients to fail to display the 993 // process causes some clients to fail to display the
921 // attachment properly. 994 // attachment properly.
922 m_Scene.AddNewSceneObject(group, !attachment, false);
923 995
924 // if attachment we set it's asset id so object updates
925 // can reflect that, if not, we set it's position in world.
926 if (!attachment) 996 if (!attachment)
927 { 997 {
928 group.ScheduleGroupForFullUpdate();
929
930 group.AbsolutePosition = pos + veclist[i]; 998 group.AbsolutePosition = pos + veclist[i];
931 } 999 m_Scene.AddNewSceneObject(group, true, false);
932
933 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
934
935 if (!attachment)
936 {
937 SceneObjectPart rootPart = group.RootPart;
938
939 if (rootPart.Shape.PCode == (byte)PCode.Prim)
940 group.ClearPartAttachmentData();
941 1000
942 // Fire on_rez 1001 // Fire on_rez
943 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); 1002 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
944 rootPart.ParentGroup.ResumeScripts(); 1003 rootPart.ParentGroup.ResumeScripts();
945 1004
946 rootPart.ScheduleFullUpdate(); 1005 group.ScheduleGroupForFullUpdate();
947 } 1006 }
1007 else
1008 m_Scene.AddNewSceneObject(group, true, false);
1009
948 1010
949// m_log.DebugFormat( 1011// m_log.DebugFormat(
950// "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", 1012// "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
@@ -953,6 +1015,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
953// remoteClient.Name); 1015// remoteClient.Name);
954 } 1016 }
955 1017
1018// group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
1019
956 if (item != null) 1020 if (item != null)
957 DoPostRezWhenFromItem(item, attachment); 1021 DoPostRezWhenFromItem(item, attachment);
958 1022
@@ -973,7 +1037,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
973 /// <param name="isAttachment"></param> 1037 /// <param name="isAttachment"></param>
974 /// <returns>true if we can processed with rezzing, false if we need to abort</returns> 1038 /// <returns>true if we can processed with rezzing, false if we need to abort</returns>
975 private bool DoPreRezWhenFromItem( 1039 private bool DoPreRezWhenFromItem(
976 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, 1040 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
977 Vector3 pos, List<Vector3> veclist, bool isAttachment) 1041 Vector3 pos, List<Vector3> veclist, bool isAttachment)
978 { 1042 {
979 UUID fromUserInventoryItemId = UUID.Zero; 1043 UUID fromUserInventoryItemId = UUID.Zero;
@@ -1033,10 +1097,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1033 // object itself before we rez. 1097 // object itself before we rez.
1034 // 1098 //
1035 // Only do these for the first object if we are rezzing a coalescence. 1099 // Only do these for the first object if we are rezzing a coalescence.
1036 if (i == 0) 1100 // nahh dont mess with coalescence objects,
1101 // the name in inventory can be change for inventory purpuses only
1102 if (objlist.Count == 1)
1037 { 1103 {
1038 rootPart.Name = item.Name; 1104 rootPart.Name = item.Name;
1039 rootPart.Description = item.Description; 1105 rootPart.Description = item.Description;
1106 }
1107
1108 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
1109 {
1040 rootPart.ObjectSaleType = item.SaleType; 1110 rootPart.ObjectSaleType = item.SaleType;
1041 rootPart.SalePrice = item.SalePrice; 1111 rootPart.SalePrice = item.SalePrice;
1042 } 1112 }
@@ -1047,20 +1117,78 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1047// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", 1117// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
1048// rootPart.OwnerID, item.Owner, item.CurrentPermissions); 1118// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
1049 1119
1050 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) 1120 if ((rootPart.OwnerID != item.Owner) ||
1121 (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 ||
1122 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
1051 { 1123 {
1052 //Need to kill the for sale here 1124 //Need to kill the for sale here
1053 rootPart.ObjectSaleType = 0; 1125 rootPart.ObjectSaleType = 0;
1054 rootPart.SalePrice = 10; 1126 rootPart.SalePrice = 10;
1055 }
1056 1127
1057 foreach (SceneObjectPart part in so.Parts) 1128 if (m_Scene.Permissions.PropagatePermissions())
1129 {
1130 foreach (SceneObjectPart part in so.Parts)
1131 {
1132 part.GroupMask = 0; // DO NOT propagate here
1133 if( part.OwnerID != part.GroupID)
1134 part.LastOwnerID = part.OwnerID;
1135 part.OwnerID = item.Owner;
1136 part.RezzerID = item.Owner;
1137 part.Inventory.ChangeInventoryOwner(item.Owner);
1138
1139 // Reconstruct the original item's base permissions. They
1140 // can be found in the lower (folded) bits.
1141 if ((item.BasePermissions & (uint)PermissionMask.FoldedMask) != 0)
1142 {
1143 // We have permissions stored there so use them
1144 part.NextOwnerMask = ((item.BasePermissions & (uint)PermissionMask.FoldedMask) << (int)PermissionMask.FoldingShift);
1145 part.NextOwnerMask |= (uint)PermissionMask.Move;
1146 }
1147 else
1148 {
1149 // This is a legacy object and we can't avoid the issues that
1150 // caused perms loss or escalation before, treat it the legacy
1151 // way.
1152 part.NextOwnerMask = item.NextPermissions;
1153 }
1154 }
1155
1156 so.ApplyNextOwnerPermissions();
1157
1158 // In case the user has changed flags on a received item
1159 // we have to apply those changes after the slam. Else we
1160 // get a net loss of permissions.
1161 // On legacy objects, this opts for a loss of permissions rather
1162 // than the previous handling that allowed escalation.
1163 foreach (SceneObjectPart part in so.Parts)
1164 {
1165 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
1166 {
1167 part.GroupMask = item.GroupPermissions & part.BaseMask;
1168 part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
1169 part.NextOwnerMask = item.NextPermissions & part.BaseMask;
1170 }
1171 }
1172
1173 }
1174 }
1175 else
1058 { 1176 {
1059 part.FromUserInventoryItemID = fromUserInventoryItemId; 1177 foreach (SceneObjectPart part in so.Parts)
1060 part.ApplyPermissionsOnRez(item, true, m_Scene); 1178 {
1179 part.FromUserInventoryItemID = fromUserInventoryItemId;
1180
1181 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1182 part.EveryoneMask = item.EveryOnePermissions;
1183 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1184 part.NextOwnerMask = item.NextPermissions;
1185 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
1186 part.GroupMask = item.GroupPermissions;
1187 }
1061 } 1188 }
1062 1189
1063 rootPart.TrimPermissions(); 1190 rootPart.TrimPermissions();
1191 so.InvalidateDeepEffectivePerms();
1064 1192
1065 if (isAttachment) 1193 if (isAttachment)
1066 so.FromItemID = item.ID; 1194 so.FromItemID = item.ID;
@@ -1184,9 +1312,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1184 protected virtual InventoryItemBase GetItem(UUID agentID, UUID itemID) 1312 protected virtual InventoryItemBase GetItem(UUID agentID, UUID itemID)
1185 { 1313 {
1186 IInventoryService invService = m_Scene.RequestModuleInterface<IInventoryService>(); 1314 IInventoryService invService = m_Scene.RequestModuleInterface<IInventoryService>();
1187 InventoryItemBase item = new InventoryItemBase(itemID, agentID); 1315 InventoryItemBase item = invService.GetItem(agentID, itemID);
1188 item = invService.GetItem(item); 1316
1189
1190 if (item != null && item.CreatorData != null && item.CreatorData != string.Empty) 1317 if (item != null && item.CreatorData != null && item.CreatorData != string.Empty)
1191 UserManagementModule.AddUser(item.CreatorIdAsUuid, item.CreatorData); 1318 UserManagementModule.AddUser(item.CreatorIdAsUuid, item.CreatorData);
1192 1319
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs
index 007ff63..01c5d3b 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs
@@ -77,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
77 scene.StartScripts(); 77 scene.StartScripts();
78 78
79 HGAssetMapper hgam = new HGAssetMapper(scene, homeUrl); 79 HGAssetMapper hgam = new HGAssetMapper(scene, homeUrl);
80 UserAccount ua 80 UserAccount ua
81 = UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "password"); 81 = UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "password");
82 82
83 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, soPartsCount, ua.PrincipalID, "part", soIdTail); 83 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, soPartsCount, ua.PrincipalID, "part", soIdTail);
@@ -93,6 +93,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
93 Assert.AreEqual(foreignUrl, ncAssetGet.CreatorID); 93 Assert.AreEqual(foreignUrl, ncAssetGet.CreatorID);
94 string xmlData = Utils.BytesToString(ncAssetGet.Data); 94 string xmlData = Utils.BytesToString(ncAssetGet.Data);
95 XmlDocument ncAssetGetXmlDoc = new XmlDocument(); 95 XmlDocument ncAssetGetXmlDoc = new XmlDocument();
96 ncAssetGetXmlDoc.XmlResolver=null;
96 ncAssetGetXmlDoc.LoadXml(xmlData); 97 ncAssetGetXmlDoc.LoadXml(xmlData);
97 98
98// Console.WriteLine(ncAssetGetXmlDoc.OuterXml); 99// Console.WriteLine(ncAssetGetXmlDoc.OuterXml);
@@ -116,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
116 XmlNode uuidAttribute = savedScriptStateNodes[0].Attributes.GetNamedItem("UUID"); 117 XmlNode uuidAttribute = savedScriptStateNodes[0].Attributes.GetNamedItem("UUID");
117 Assert.NotNull(uuidAttribute); 118 Assert.NotNull(uuidAttribute);
118 // XXX: To check the actual UUID attribute we would have to do some work to retreive the UUID of the task 119 // XXX: To check the actual UUID attribute we would have to do some work to retreive the UUID of the task
119 // item created earlier. 120 // item created earlier.
120 } 121 }
121 122
122 private void RezScript(Scene scene, UUID soId, string script, string itemName, UUID userId) 123 private void RezScript(Scene scene, UUID soId, string script, string itemName, UUID userId)
@@ -131,9 +132,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
131 // immediately for tests rather than chunter through it's threaded mechanisms. 132 // immediately for tests rather than chunter through it's threaded mechanisms.
132 AutoResetEvent chatEvent = new AutoResetEvent(false); 133 AutoResetEvent chatEvent = new AutoResetEvent(false);
133 134
134 scene.EventManager.OnChatFromWorld += (s, c) => 135 scene.EventManager.OnChatFromWorld += (s, c) =>
135 { 136 {
136// Console.WriteLine("Got chat [{0}]", c.Message); 137// Console.WriteLine("Got chat [{0}]", c.Message);
137 chatEvent.Set(); 138 chatEvent.Set();
138 }; 139 };
139 140
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
index 1d91165..de29ae9 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -48,12 +48,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
48{ 48{
49 [TestFixture] 49 [TestFixture]
50 public class InventoryAccessModuleTests : OpenSimTestCase 50 public class InventoryAccessModuleTests : OpenSimTestCase
51 { 51 {
52 protected TestScene m_scene; 52 protected TestScene m_scene;
53 protected BasicInventoryAccessModule m_iam; 53 protected BasicInventoryAccessModule m_iam;
54 protected UUID m_userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); 54 protected UUID m_userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
55 protected TestClient m_tc; 55 protected TestClient m_tc;
56 56
57 [SetUp] 57 [SetUp]
58 public override void SetUp() 58 public override void SetUp()
59 { 59 {
@@ -68,31 +68,32 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
68 SceneHelpers sceneHelpers = new SceneHelpers(); 68 SceneHelpers sceneHelpers = new SceneHelpers();
69 m_scene = sceneHelpers.SetupScene(); 69 m_scene = sceneHelpers.SetupScene();
70 SceneHelpers.SetupSceneModules(m_scene, config, m_iam); 70 SceneHelpers.SetupSceneModules(m_scene, config, m_iam);
71 71
72 // Create user 72 // Create user
73 string userFirstName = "Jock"; 73 string userFirstName = "Jock";
74 string userLastName = "Stirrup"; 74 string userLastName = "Stirrup";
75 string userPassword = "troll"; 75 string userPassword = "troll";
76 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword); 76 UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword);
77 77
78 AgentCircuitData acd = new AgentCircuitData(); 78 AgentCircuitData acd = new AgentCircuitData();
79 acd.AgentID = m_userId; 79 acd.AgentID = m_userId;
80 m_tc = new TestClient(acd, m_scene); 80 m_tc = new TestClient(acd, m_scene);
81 } 81 }
82 82
83 [Test] 83 [Test]
84 public void TestRezCoalescedObject() 84 public void TestRezCoalescedObject()
85 { 85 {
86/*
86 TestHelpers.InMethod(); 87 TestHelpers.InMethod();
87// log4net.Config.XmlConfigurator.Configure(); 88// log4net.Config.XmlConfigurator.Configure();
88 89
89 // Create asset 90 // Create asset
90 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, m_userId, "Object1", 0x20); 91 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, m_userId, "Object1", 0x20);
91 object1.AbsolutePosition = new Vector3(15, 30, 45); 92 object1.AbsolutePosition = new Vector3(15, 30, 45);
92 93
93 SceneObjectGroup object2 = SceneHelpers.CreateSceneObject(1, m_userId, "Object2", 0x40); 94 SceneObjectGroup object2 = SceneHelpers.CreateSceneObject(1, m_userId, "Object2", 0x40);
94 object2.AbsolutePosition = new Vector3(25, 50, 75); 95 object2.AbsolutePosition = new Vector3(25, 50, 75);
95 96
96 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_userId, object1, object2); 97 CoalescedSceneObjects coa = new CoalescedSceneObjects(m_userId, object1, object2);
97 98
98 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 99 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
@@ -106,45 +107,46 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
106 item1.Name = item1Name; 107 item1.Name = item1Name;
107 item1.AssetID = asset1.FullID; 108 item1.AssetID = asset1.FullID;
108 item1.ID = item1Id; 109 item1.ID = item1Id;
109 InventoryFolderBase objsFolder 110 InventoryFolderBase objsFolder
110 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; 111 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0];
111 item1.Folder = objsFolder.ID; 112 item1.Folder = objsFolder.ID;
112 item1.Flags |= (uint)InventoryItemFlags.ObjectHasMultipleItems; 113 item1.Flags |= (uint)InventoryItemFlags.ObjectHasMultipleItems;
113 m_scene.AddInventoryItem(item1); 114 m_scene.AddInventoryItem(item1);
114 115
115 SceneObjectGroup so 116 SceneObjectGroup so
116 = m_iam.RezObject( 117 = m_iam.RezObject(
117 m_tc, item1Id, new Vector3(100, 100, 100), Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); 118 m_tc, item1Id, new Vector3(100, 100, 100), Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false);
118 119
119 Assert.That(so, Is.Not.Null); 120 Assert.That(so, Is.Not.Null);
120 121
121 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(2)); 122 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(2));
122 123
123 SceneObjectPart retrievedObj1Part = m_scene.GetSceneObjectPart(object1.Name); 124 SceneObjectPart retrievedObj1Part = m_scene.GetSceneObjectPart(object1.Name);
124 Assert.That(retrievedObj1Part, Is.Null); 125 Assert.That(retrievedObj1Part, Is.Null);
125 126
126 retrievedObj1Part = m_scene.GetSceneObjectPart(item1.Name); 127 retrievedObj1Part = m_scene.GetSceneObjectPart(item1.Name);
127 Assert.That(retrievedObj1Part, Is.Not.Null); 128 Assert.That(retrievedObj1Part, Is.Not.Null);
128 Assert.That(retrievedObj1Part.Name, Is.EqualTo(item1.Name)); 129 Assert.That(retrievedObj1Part.Name, Is.EqualTo(item1.Name));
129 130
130 // Bottom of coalescence is placed on ground, hence we end up with 100.5 rather than 85 since the bottom 131 // Bottom of coalescence is placed on ground, hence we end up with 100.5 rather than 85 since the bottom
131 // object is unit square. 132 // object is unit square.
132 Assert.That(retrievedObj1Part.AbsolutePosition, Is.EqualTo(new Vector3(95, 90, 100.5f))); 133 Assert.That(retrievedObj1Part.AbsolutePosition, Is.EqualTo(new Vector3(95, 90, 100.5f)));
133 134
134 SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name); 135 SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name);
135 Assert.That(retrievedObj2Part, Is.Not.Null); 136 Assert.That(retrievedObj2Part, Is.Not.Null);
136 Assert.That(retrievedObj2Part.Name, Is.EqualTo(object2.Name)); 137 Assert.That(retrievedObj2Part.Name, Is.EqualTo(object2.Name));
137 Assert.That(retrievedObj2Part.AbsolutePosition, Is.EqualTo(new Vector3(105, 110, 130.5f))); 138 Assert.That(retrievedObj2Part.AbsolutePosition, Is.EqualTo(new Vector3(105, 110, 130.5f)));
138 } 139*/
139 140 }
141
140 [Test] 142 [Test]
141 public void TestRezObject() 143 public void TestRezObject()
142 { 144 {
143 TestHelpers.InMethod(); 145 TestHelpers.InMethod();
144// log4net.Config.XmlConfigurator.Configure(); 146// log4net.Config.XmlConfigurator.Configure();
145 147
146 // Create asset 148 // Create asset
147 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, m_userId, "My Little Dog Object", 0x40); 149 SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, m_userId, "My Little Dog Object", 0x40);
148 150
149 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); 151 UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060");
150 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); 152 AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1);
@@ -157,17 +159,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
157 item1.Name = item1Name; 159 item1.Name = item1Name;
158 item1.AssetID = asset1.FullID; 160 item1.AssetID = asset1.FullID;
159 item1.ID = item1Id; 161 item1.ID = item1Id;
160 InventoryFolderBase objsFolder 162 InventoryFolderBase objsFolder
161 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; 163 = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0];
162 item1.Folder = objsFolder.ID; 164 item1.Folder = objsFolder.ID;
163 m_scene.AddInventoryItem(item1); 165 m_scene.AddInventoryItem(item1);
164 166
165 SceneObjectGroup so 167 SceneObjectGroup so
166 = m_iam.RezObject( 168 = m_iam.RezObject(
167 m_tc, item1Id, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); 169 m_tc, item1Id, UUID.Zero, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false);
168 170
169 Assert.That(so, Is.Not.Null); 171 Assert.That(so, Is.Not.Null);
170 172
171 SceneObjectPart retrievedPart = m_scene.GetSceneObjectPart(so.UUID); 173 SceneObjectPart retrievedPart = m_scene.GetSceneObjectPart(so.UUID);
172 Assert.That(retrievedPart, Is.Not.Null); 174 Assert.That(retrievedPart, Is.Not.Null);
173 } 175 }
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index 862f0b7..5d77201 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -126,7 +126,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
126 return; 126 return;
127 127
128 // This will never run more than once, even if the region is restarted 128 // This will never run more than once, even if the region is restarted
129 if (!m_HasRunOnce) 129 if (!m_HasRunOnce)
130 { 130 {
131 LoadLibrariesFromArchives(); 131 LoadLibrariesFromArchives();
132 //DumpLibrary(); 132 //DumpLibrary();
@@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
178 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, simpleName, iarFileName, false); 178 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, simpleName, iarFileName, false);
179 try 179 try
180 { 180 {
181 HashSet<InventoryNodeBase> nodes = archread.Execute(); 181 Dictionary<UUID, InventoryNodeBase> nodes = archread.Execute();
182 if (nodes != null && nodes.Count == 0) 182 if (nodes != null && nodes.Count == 0)
183 { 183 {
184 // didn't find the subfolder with the given name; place it on the top 184 // didn't find the subfolder with the given name; place it on the top
@@ -188,7 +188,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
188 archread.Execute(); 188 archread.Execute();
189 } 189 }
190 190
191 foreach (InventoryNodeBase node in nodes) 191 foreach (InventoryNodeBase node in nodes.Values)
192 FixPerms(node); 192 FixPerms(node);
193 } 193 }
194 catch (Exception e) 194 catch (Exception e)
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
index e1e1838..c1a9457 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
@@ -103,13 +103,8 @@ namespace OpenSim.Region.CoreModules.Framework.Library
103 { 103 {
104 InventoryItemBase[] itemColl = new InventoryItemBase[itemIDs.Length]; 104 InventoryItemBase[] itemColl = new InventoryItemBase[itemIDs.Length];
105 int i = 0; 105 int i = 0;
106 InventoryItemBase item = new InventoryItemBase();
107 item.Owner = principalID;
108 foreach (UUID fid in itemIDs) 106 foreach (UUID fid in itemIDs)
109 { 107 itemColl[i++] = GetItem(principalID, fid);
110 item.ID = fid;
111 itemColl[i++] = GetItem(item);
112 }
113 108
114 return itemColl; 109 return itemColl;
115 } 110 }
@@ -239,14 +234,14 @@ namespace OpenSim.Region.CoreModules.Framework.Library
239 /// </summary> 234 /// </summary>
240 /// <param name="item"></param> 235 /// <param name="item"></param>
241 /// <returns></returns> 236 /// <returns></returns>
242 public InventoryItemBase GetItem(InventoryItemBase item) { return null; } 237 public InventoryItemBase GetItem(UUID principalID, UUID itemID) { return null; }
243 238
244 /// <summary> 239 /// <summary>
245 /// Get a folder, given by its UUID 240 /// Get a folder, given by its UUID
246 /// </summary> 241 /// </summary>
247 /// <param name="folder"></param> 242 /// <param name="folder"></param>
248 /// <returns></returns> 243 /// <returns></returns>
249 public InventoryFolderBase GetFolder(InventoryFolderBase folder) { return null; } 244 public InventoryFolderBase GetFolder(UUID principalID, UUID folderID) { return null; }
250 245
251 /// <summary> 246 /// <summary>
252 /// Does the given user have an inventory structure? 247 /// Does the given user have an inventory structure?
@@ -264,11 +259,11 @@ namespace OpenSim.Region.CoreModules.Framework.Library
264 259
265 /// <summary> 260 /// <summary>
266 /// Get the union of permissions of all inventory items 261 /// Get the union of permissions of all inventory items
267 /// that hold the given assetID. 262 /// that hold the given assetID.
268 /// </summary> 263 /// </summary>
269 /// <param name="userID"></param> 264 /// <param name="userID"></param>
270 /// <param name="assetID"></param> 265 /// <param name="assetID"></param>
271 /// <returns>The permissions or 0 if no such asset is found in 266 /// <returns>The permissions or 0 if no such asset is found in
272 /// the user's inventory</returns> 267 /// the user's inventory</returns>
273 public int GetAssetPermissions(UUID userID, UUID assetID) { return 0; } 268 public int GetAssetPermissions(UUID userID, UUID assetID) { return 0; }
274 } 269 }
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index 64feec1..fb3d31c 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -44,7 +44,7 @@ using Mono.Addins;
44namespace OpenSim.Region.CoreModules.Framework.Monitoring 44namespace OpenSim.Region.CoreModules.Framework.Monitoring
45{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MonitorModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MonitorModule")]
47 public class MonitorModule : INonSharedRegionModule 47 public class MonitorModule : INonSharedRegionModule
48 { 48 {
49 /// <summary> 49 /// <summary>
50 /// Is this module enabled? 50 /// Is this module enabled?
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
78 78
79 if (cnfg != null) 79 if (cnfg != null)
80 Enabled = cnfg.GetBoolean("Enabled", true); 80 Enabled = cnfg.GetBoolean("Enabled", true);
81 81
82 if (!Enabled) 82 if (!Enabled)
83 return; 83 return;
84 84
@@ -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));
@@ -433,7 +433,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
433 MakeStat("ScriptLines", "lines/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[20]; }); 433 MakeStat("ScriptLines", "lines/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[20]; });
434 MakeStat("SimSpareMS", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[21]; }); 434 MakeStat("SimSpareMS", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[21]; });
435 } 435 }
436 436
437 private void UnRegisterStatsManagerRegionStatistics() 437 private void UnRegisterStatsManagerRegionStatistics()
438 { 438 {
439 foreach (Stat stat in registeredStats) 439 foreach (Stat stat in registeredStats)
@@ -443,6 +443,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
443 } 443 }
444 registeredStats.Clear(); 444 registeredStats.Clear();
445 } 445 }
446 446
447 } 447 }
448} \ No newline at end of file 448} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
index 3849996..c04d856 100644
--- a/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
@@ -135,7 +135,7 @@ namespace OpenSim.Region.CoreModules.Framework.Search
135 135
136 #endregion ISharedRegionModule 136 #endregion ISharedRegionModule
137 137
138 138
139 #region Event Handlers 139 #region Event Handlers
140 140
141 void EventManager_OnMakeRootAgent(ScenePresence sp) 141 void EventManager_OnMakeRootAgent(ScenePresence sp)
diff --git a/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
index 3abacbd..2c74c0e 100644
--- a/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
@@ -48,31 +48,16 @@ namespace OpenSim.Region.CoreModules.Framework
48 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private readonly List<Scene> m_scenes = new List<Scene>(); 50 private readonly List<Scene> m_scenes = new List<Scene>();
51 private System.Timers.Timer m_timer = new System.Timers.Timer(); 51 private JobEngine m_processorJobEngine;
52
53 private Queue<Action> m_RequestQueue = new Queue<Action>();
54 private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
55 private int m_Interval;
56 52
57 #region ISharedRegionModule 53 #region ISharedRegionModule
58 54
59 public void Initialise(IConfigSource config) 55 public void Initialise(IConfigSource config)
60 { 56 {
61 m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000); 57 m_processorJobEngine = new JobEngine(
62 58 "ServiceThrottle","ServiceThrottle");
63 m_timer = new System.Timers.Timer(); 59 m_processorJobEngine.RequestProcessTimeoutOnStop = 31000; // many webrequests have 30s expire
64 m_timer.AutoReset = false; 60 m_processorJobEngine.Start();
65 m_timer.Enabled = true;
66 m_timer.Interval = 15000; // 15 secs at first
67 m_timer.Elapsed += ProcessQueue;
68 m_timer.Start();
69
70 //WorkManager.StartThread(
71 // ProcessQueue,
72 // "GridServiceRequestThread",
73 // ThreadPriority.BelowNormal,
74 // true,
75 // false);
76 } 61 }
77 62
78 public void AddRegion(Scene scene) 63 public void AddRegion(Scene scene)
@@ -82,7 +67,6 @@ namespace OpenSim.Region.CoreModules.Framework
82 m_scenes.Add(scene); 67 m_scenes.Add(scene);
83 scene.RegisterModuleInterface<IServiceThrottleModule>(this); 68 scene.RegisterModuleInterface<IServiceThrottleModule>(this);
84 scene.EventManager.OnNewClient += OnNewClient; 69 scene.EventManager.OnNewClient += OnNewClient;
85 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
86 } 70 }
87 } 71 }
88 72
@@ -105,6 +89,7 @@ namespace OpenSim.Region.CoreModules.Framework
105 89
106 public void Close() 90 public void Close()
107 { 91 {
92 m_processorJobEngine.Stop();
108 } 93 }
109 94
110 public string Name 95 public string Name
@@ -126,38 +111,32 @@ namespace OpenSim.Region.CoreModules.Framework
126 client.OnRegionHandleRequest += OnRegionHandleRequest; 111 client.OnRegionHandleRequest += OnRegionHandleRequest;
127 } 112 }
128 113
129 void OnMakeRootAgent(ScenePresence obj)
130 {
131 lock (m_timer)
132 {
133 if (!m_timer.Enabled)
134 {
135 m_timer.Interval = m_Interval;
136 m_timer.Enabled = true;
137 m_timer.Start();
138 }
139 }
140 }
141
142 public void OnRegionHandleRequest(IClientAPI client, UUID regionID) 114 public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
143 { 115 {
144 //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID); 116 //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
145 ulong handle = 0;
146 if (IsLocalRegionHandle(regionID, out handle))
147 {
148 client.SendRegionHandle(regionID, handle);
149 return;
150 }
151
152 Action action = delegate 117 Action action = delegate
153 { 118 {
154 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID); 119 if(!client.IsActive)
120 return;
121
122 if(m_scenes.Count == 0)
123 return;
124
125 Scene baseScene = m_scenes[0];
126
127 if(baseScene == null || baseScene.ShuttingDown)
128 return;
129
130 GridRegion r = baseScene.GridService.GetRegionByUUID(UUID.Zero, regionID);
131
132 if(!client.IsActive)
133 return;
155 134
156 if (r != null && r.RegionHandle != 0) 135 if (r != null && r.RegionHandle != 0)
157 client.SendRegionHandle(regionID, r.RegionHandle); 136 client.SendRegionHandle(regionID, r.RegionHandle);
158 }; 137 };
159 138
160 Enqueue("region", regionID.ToString(), action); 139 m_processorJobEngine.QueueJob("regionHandle", action, regionID.ToString());
161 } 140 }
162 141
163 #endregion Events 142 #endregion Events
@@ -166,91 +145,10 @@ namespace OpenSim.Region.CoreModules.Framework
166 145
167 public void Enqueue(string category, string itemid, Action continuation) 146 public void Enqueue(string category, string itemid, Action continuation)
168 { 147 {
169 lock (m_RequestQueue) 148 m_processorJobEngine.QueueJob(category, continuation, itemid);
170 {
171 if (m_Pending.ContainsKey(category))
172 {
173 if (m_Pending[category].Contains(itemid))
174 // Don't enqueue, it's already pending
175 return;
176 }
177 else
178 m_Pending.Add(category, new List<string>());
179
180 m_Pending[category].Add(itemid);
181
182 m_RequestQueue.Enqueue(delegate
183 {
184 lock (m_RequestQueue)
185 m_Pending[category].Remove(itemid);
186
187 continuation();
188 });
189 }
190 } 149 }
191 150
192 #endregion IServiceThrottleModule 151 #endregion IServiceThrottleModule
193
194 #region Process Continuation Queue
195
196 private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
197 {
198 //m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
199
200 while (m_RequestQueue.Count > 0)
201 {
202 Action continuation = null;
203 lock (m_RequestQueue)
204 continuation = m_RequestQueue.Dequeue();
205
206 if (continuation != null)
207 continuation();
208 }
209
210 if (AreThereRootAgents())
211 {
212 lock (m_timer)
213 {
214 m_timer.Interval = 1000; // 1 sec
215 m_timer.Enabled = true;
216 m_timer.Start();
217 }
218 }
219 else
220 lock (m_timer)
221 m_timer.Enabled = false;
222
223 }
224
225 #endregion Process Continuation Queue
226
227 #region Misc
228
229 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
230 {
231 regionHandle = 0;
232 foreach (Scene s in m_scenes)
233 if (s.RegionInfo.RegionID == regionID)
234 {
235 regionHandle = s.RegionInfo.RegionHandle;
236 return true;
237 }
238 return false;
239 }
240
241 private bool AreThereRootAgents()
242 {
243 foreach (Scene s in m_scenes)
244 {
245 foreach (ScenePresence sp in s.GetScenePresences())
246 if (!sp.IsChildAgent)
247 return true;
248 }
249
250 return false;
251 }
252
253 #endregion Misc
254 } 152 }
255 153
256} 154}
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
index f3436d1..3e6c8b5 100644
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
@@ -45,14 +45,14 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
45 public class BinaryLoggingModule : INonSharedRegionModule 45 public class BinaryLoggingModule : INonSharedRegionModule
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 protected bool m_collectStats; 49 protected bool m_collectStats;
50 protected Scene m_scene = null; 50 protected Scene m_scene = null;
51 51
52 public string Name { get { return "Binary Statistics Logging Module"; } } 52 public string Name { get { return "Binary Statistics Logging Module"; } }
53 public Type ReplaceableInterface { get { return null; } } 53 public Type ReplaceableInterface { get { return null; } }
54 54
55 public void Initialise(IConfigSource source) 55 public void Initialise(IConfigSource source)
56 { 56 {
57 try 57 try
58 { 58 {
@@ -81,23 +81,23 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
81 // if it doesn't work, we don't collect anything 81 // if it doesn't work, we don't collect anything
82 } 82 }
83 } 83 }
84 84
85 public void AddRegion(Scene scene) 85 public void AddRegion(Scene scene)
86 { 86 {
87 m_scene = scene; 87 m_scene = scene;
88 } 88 }
89 89
90 public void RemoveRegion(Scene scene) 90 public void RemoveRegion(Scene scene)
91 { 91 {
92 } 92 }
93 93
94 public void RegionLoaded(Scene scene) 94 public void RegionLoaded(Scene scene)
95 { 95 {
96 if (m_collectStats) 96 if (m_collectStats)
97 m_scene.StatsReporter.OnSendStatsResult += LogSimStats; 97 m_scene.StatsReporter.OnSendStatsResult += LogSimStats;
98 } 98 }
99 99
100 public void Close() 100 public void Close()
101 { 101 {
102 } 102 }
103 103
@@ -107,12 +107,12 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
107 public string Path; 107 public string Path;
108 public System.IO.BinaryWriter Log; 108 public System.IO.BinaryWriter Log;
109 } 109 }
110 110
111 static StatLogger m_statLog = null; 111 static StatLogger m_statLog = null;
112 static TimeSpan m_statLogPeriod = TimeSpan.FromSeconds(300); 112 static TimeSpan m_statLogPeriod = TimeSpan.FromSeconds(300);
113 static string m_statsDir = String.Empty; 113 static string m_statsDir = String.Empty;
114 static Object m_statLockObject = new Object(); 114 static Object m_statLockObject = new Object();
115 115
116 private void LogSimStats(SimStats stats) 116 private void LogSimStats(SimStats stats)
117 { 117 {
118 SimStatsPacket pack = new SimStatsPacket(); 118 SimStatsPacket pack = new SimStatsPacket();
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index 7b89c2c..3e0a610 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
52 52
53 #region ISharedRegionModule 53 #region ISharedRegionModule
54 54
55 public new void Initialise(IConfigSource config) 55 public override void Initialise(IConfigSource config)
56 { 56 {
57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null); 57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null);
58 if (umanmod == Name) 58 if (umanmod == Name)
@@ -111,7 +111,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
111 } 111 }
112 112
113 // This is it! Let's ask the other world 113 // This is it! Let's ask the other world
114 if (words[0].Contains(".")) 114 if (words[0].Contains("."))
115 { 115 {
116 string[] names = words[0].Split(new char[] { '.' }); 116 string[] names = words[0].Split(new char[] { '.' });
117 if (names.Length >= 2) 117 if (names.Length >= 2)
@@ -130,7 +130,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
130 } 130 }
131 131
132 UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uriStr); 132 UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uriStr);
133 133
134 UUID userID = UUID.Zero; 134 UUID userID = UUID.Zero;
135 try 135 try
136 { 136 {
@@ -140,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
140 { 140 {
141 m_log.Debug("[USER MANAGEMENT MODULE]: GetUUID call failed ", e); 141 m_log.Debug("[USER MANAGEMENT MODULE]: GetUUID call failed ", e);
142 } 142 }
143 143
144 if (!userID.Equals(UUID.Zero)) 144 if (!userID.Equals(UUID.Zero))
145 { 145 {
146 UserData ud = new UserData(); 146 UserData ud = new UserData();
@@ -163,8 +163,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
163 //{ 163 //{
164 // foreach (UserData d in m_UserCache.Values) 164 // foreach (UserData d in m_UserCache.Values)
165 // { 165 // {
166 // if (d.LastName.StartsWith("@") && 166 // if (d.LastName.StartsWith("@") &&
167 // (d.FirstName.ToLower().StartsWith(query.ToLower()) || 167 // (d.FirstName.ToLower().StartsWith(query.ToLower()) ||
168 // d.LastName.ToLower().StartsWith(query.ToLower()))) 168 // d.LastName.ToLower().StartsWith(query.ToLower())))
169 // users.Add(d); 169 // users.Add(d);
170 // } 170 // }
@@ -172,4 +172,4 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
172 } 172 }
173 173
174 } 174 }
175} \ No newline at end of file 175}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
index 4e3b7e5..9d91aa3 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement.Tests
37{ 37{
38 [TestFixture] 38 [TestFixture]
39 public class HGUserManagementModuleTests : OpenSimTestCase 39 public class HGUserManagementModuleTests : OpenSimTestCase
40 { 40 {
41 /// <summary> 41 /// <summary>
42 /// Test that a new HG agent (i.e. one without a user account) has their name cached in the UMM upon creation. 42 /// Test that a new HG agent (i.e. one without a user account) has their name cached in the UMM upon creation.
43 /// </summary> 43 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 7ecbd26..2695464 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
66 66
67 #region ISharedRegionModule 67 #region ISharedRegionModule
68 68
69 public void Initialise(IConfigSource config) 69 public virtual void Initialise(IConfigSource config)
70 { 70 {
71 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name); 71 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name);
72 if (umanmod == Name) 72 if (umanmod == Name)
@@ -88,7 +88,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
88 m_DisplayChangingHomeURI = userManagementConfig.GetBoolean("DisplayChangingHomeURI", false); 88 m_DisplayChangingHomeURI = userManagementConfig.GetBoolean("DisplayChangingHomeURI", false);
89 } 89 }
90 90
91 public bool IsSharedModule 91 public virtual bool IsSharedModule
92 { 92 {
93 get { return true; } 93 get { return true; }
94 } 94 }
@@ -98,12 +98,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
98 get { return "BasicUserManagementModule"; } 98 get { return "BasicUserManagementModule"; }
99 } 99 }
100 100
101 public Type ReplaceableInterface 101 public virtual Type ReplaceableInterface
102 { 102 {
103 get { return null; } 103 get { return null; }
104 } 104 }
105 105
106 public void AddRegion(Scene scene) 106 public virtual void AddRegion(Scene scene)
107 { 107 {
108 if (m_Enabled) 108 if (m_Enabled)
109 { 109 {
@@ -119,7 +119,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
119 } 119 }
120 } 120 }
121 121
122 public void RemoveRegion(Scene scene) 122 public virtual void RemoveRegion(Scene scene)
123 { 123 {
124 if (m_Enabled) 124 if (m_Enabled)
125 { 125 {
@@ -131,17 +131,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
131 } 131 }
132 } 132 }
133 133
134 public void RegionLoaded(Scene s) 134 public virtual void RegionLoaded(Scene s)
135 { 135 {
136 if (m_Enabled && m_ServiceThrottle == null) 136 if (m_Enabled && m_ServiceThrottle == null)
137 m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>(); 137 m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
138 } 138 }
139 139
140 public void PostInitialise() 140 public virtual void PostInitialise()
141 { 141 {
142 } 142 }
143 143
144 public void Close() 144 public virtual void Close()
145 { 145 {
146 lock (m_Scenes) 146 lock (m_Scenes)
147 { 147 {
@@ -157,31 +157,34 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
157 157
158 #region Event Handlers 158 #region Event Handlers
159 159
160 void EventManager_OnPrimsLoaded(Scene s) 160 protected virtual void EventManager_OnPrimsLoaded(Scene s)
161 { 161 {
162 // let's sniff all the user names referenced by objects in the scene 162 // let's sniff all the user names referenced by objects in the scene
163 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length); 163 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
164 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); 164 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
165 } 165 }
166 166
167 void EventManager_OnNewClient(IClientAPI client) 167 protected virtual void EventManager_OnNewClient(IClientAPI client)
168 { 168 {
169 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); 169 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed);
170 client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest); 170 client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest);
171 client.OnAvatarPickerRequest += new AvatarPickerRequest(HandleAvatarPickerRequest); 171 client.OnAvatarPickerRequest += new AvatarPickerRequest(HandleAvatarPickerRequest);
172 } 172 }
173 173
174 void HandleConnectionClosed(IClientAPI client) 174 protected virtual void HandleConnectionClosed(IClientAPI client)
175 { 175 {
176 client.OnNameFromUUIDRequest -= new UUIDNameRequest(HandleUUIDNameRequest); 176 client.OnNameFromUUIDRequest -= new UUIDNameRequest(HandleUUIDNameRequest);
177 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); 177 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
178 client.OnConnectionClosed -= new Action<IClientAPI>(HandleConnectionClosed);
178 } 179 }
179 180
180 void HandleUUIDNameRequest(UUID uuid, IClientAPI client) 181 protected virtual void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
181 { 182 {
182// m_log.DebugFormat( 183// m_log.DebugFormat(
183// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", 184// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
184// uuid, remote_client.Name); 185// uuid, remote_client.Name);
186 if(m_Scenes.Count <= 0)
187 return;
185 188
186 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 189 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
187 { 190 {
@@ -204,7 +207,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
204 } 207 }
205 208
206 // Not found in cache, queue continuation 209 // Not found in cache, queue continuation
207 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate 210 m_ServiceThrottle.Enqueue("uuidname", uuid.ToString(), delegate
208 { 211 {
209 //m_log.DebugFormat("[YYY]: Name request {0}", uuid); 212 //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
210 213
@@ -214,9 +217,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
214 // So to avoid clients 217 // So to avoid clients
215 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will 218 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
216 // instead drop the request entirely. 219 // instead drop the request entirely.
220 if(!client.IsActive)
221 return;
217 if (GetUser(uuid, out user)) 222 if (GetUser(uuid, out user))
218 { 223 {
219 client.SendNameReply(uuid, user.FirstName, user.LastName); 224 if(client.IsActive)
225 client.SendNameReply(uuid, user.FirstName, user.LastName);
220 } 226 }
221// else 227// else
222// m_log.DebugFormat( 228// m_log.DebugFormat(
@@ -226,7 +232,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
226 } 232 }
227 } 233 }
228 234
229 public void HandleAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query) 235 public virtual void HandleAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query)
230 { 236 {
231 //EventManager.TriggerAvatarPickerRequest(); 237 //EventManager.TriggerAvatarPickerRequest();
232 238
@@ -286,8 +292,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
286 292
287 #region IPeople 293 #region IPeople
288 294
289 public List<UserData> GetUserData(string query, int page_size, int page_number) 295 public virtual List<UserData> GetUserData(string query, int page_size, int page_number)
290 { 296 {
297 if(m_Scenes.Count <= 0)
298 return new List<UserData>();;
299
291 // search the user accounts service 300 // search the user accounts service
292 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); 301 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
293 302
@@ -323,7 +332,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
323 332
324 #endregion IPeople 333 #endregion IPeople
325 334
326 private void CacheCreators(SceneObjectGroup sog) 335 protected virtual void CacheCreators(SceneObjectGroup sog)
327 { 336 {
328 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); 337 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
329 AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData); 338 AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);
@@ -336,9 +345,108 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
336 } 345 }
337 } 346 }
338 347
348 /// <summary>
349 ///
350 /// </summary>
351 /// <param name="uuid"></param>
352 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
353 /// <returns></returns>
354 protected virtual bool TryGetUserNames(UUID uuid, string[] names)
355 {
356 if (names == null)
357 names = new string[2];
358
359 if (TryGetUserNamesFromCache(uuid, names))
360 return true;
361
362 if (TryGetUserNamesFromServices(uuid, names))
363 return true;
364
365 return false;
366 }
367
368 protected virtual bool TryGetUserNamesFromCache(UUID uuid, string[] names)
369 {
370 lock (m_UserCache)
371 {
372 if (m_UserCache.ContainsKey(uuid))
373 {
374 names[0] = m_UserCache[uuid].FirstName;
375 names[1] = m_UserCache[uuid].LastName;
376
377 return true;
378 }
379 }
380
381 return false;
382 }
383
384 /// <summary>
385 /// Try to get the names bound to the given uuid, from the services.
386 /// </summary>
387 /// <returns>True if the name was found, false if not.</returns>
388 /// <param name='uuid'></param>
389 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
390 protected virtual bool TryGetUserNamesFromServices(UUID uuid, string[] names)
391 {
392 if(m_Scenes.Count <= 0)
393 return false;
394
395 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
396
397 if (account != null)
398 {
399 names[0] = account.FirstName;
400 names[1] = account.LastName;
401
402 UserData user = new UserData();
403 user.FirstName = account.FirstName;
404 user.LastName = account.LastName;
405
406 lock (m_UserCache)
407 m_UserCache[uuid] = user;
408
409 return true;
410 }
411 else
412 {
413 // Let's try the GridUser service
414 GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
415 if (uInfo != null)
416 {
417 string url, first, last, tmp;
418 UUID u;
419 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
420 {
421 AddUser(uuid, first, last, url);
422
423 if (m_UserCache.ContainsKey(uuid))
424 {
425 names[0] = m_UserCache[uuid].FirstName;
426 names[1] = m_UserCache[uuid].LastName;
427
428 return true;
429 }
430 }
431 else
432 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
433 }
434// else
435// {
436// m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
437// }
438
439 names[0] = "Unknown";
440 names[1] = "UserUMMTGUN9";
441
442 return false;
443 }
444 }
445
446
339 #region IUserManagement 447 #region IUserManagement
340 448
341 public UUID GetUserIdByName(string name) 449 public virtual UUID GetUserIdByName(string name)
342 { 450 {
343 string[] parts = name.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); 451 string[] parts = name.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
344 if (parts.Length < 2) 452 if (parts.Length < 2)
@@ -347,8 +455,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
347 return GetUserIdByName(parts[0], parts[1]); 455 return GetUserIdByName(parts[0], parts[1]);
348 } 456 }
349 457
350 public UUID GetUserIdByName(string firstName, string lastName) 458 public virtual UUID GetUserIdByName(string firstName, string lastName)
351 { 459 {
460 if(m_Scenes.Count <= 0)
461 return UUID.Zero;
462
352 // TODO: Optimize for reverse lookup if this gets used by non-console commands. 463 // TODO: Optimize for reverse lookup if this gets used by non-console commands.
353 lock (m_UserCache) 464 lock (m_UserCache)
354 { 465 {
@@ -367,14 +478,159 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
367 return UUID.Zero; 478 return UUID.Zero;
368 } 479 }
369 480
370 public string GetUserName(UUID uuid) 481 public virtual string GetUserName(UUID uuid)
371 { 482 {
372 UserData user; 483 UserData user;
373 GetUser(uuid, out user); 484 GetUser(uuid, out user);
374 return user.FirstName + " " + user.LastName; 485 return user.FirstName + " " + user.LastName;
375 } 486 }
376 487
377 public string GetUserHomeURL(UUID userID) 488 public virtual Dictionary<UUID,string> GetUsersNames(string[] ids)
489 {
490 Dictionary<UUID,string> ret = new Dictionary<UUID,string>();
491 if(m_Scenes.Count <= 0)
492 return ret;
493
494 List<string> missing = new List<string>();
495 Dictionary<UUID,string> untried = new Dictionary<UUID, string>();
496
497 // look in cache
498 UserData userdata = new UserData();
499
500 UUID uuid = UUID.Zero;
501 foreach(string id in ids)
502 {
503 if(UUID.TryParse(id, out uuid))
504 {
505 lock (m_UserCache)
506 {
507 if (m_UserCache.TryGetValue(uuid, out userdata) &&
508 userdata.FirstName != "Unknown" && userdata.FirstName != string.Empty)
509 {
510 string name = userdata.FirstName + " " + userdata.LastName;
511
512 if(userdata.HasGridUserTried)
513 ret[uuid] = name;
514 else
515 {
516 untried[uuid] = name;
517 missing.Add(id);
518 }
519 }
520 else
521 missing.Add(id);
522 }
523 }
524 }
525
526 if(missing.Count == 0)
527 return ret;
528
529 // try user account service
530 List<UserAccount> accounts = m_Scenes[0].UserAccountService.GetUserAccounts(
531 m_Scenes[0].RegionInfo.ScopeID, missing);
532
533 if(accounts.Count != 0)
534 {
535 foreach(UserAccount uac in accounts)
536 {
537 if(uac != null)
538 {
539 string name = uac.FirstName + " " + uac.LastName;
540 ret[uac.PrincipalID] = name;
541 missing.Remove(uac.PrincipalID.ToString()); // slowww
542 untried.Remove(uac.PrincipalID);
543
544 userdata = new UserData();
545 userdata.Id = uac.PrincipalID;
546 userdata.FirstName = uac.FirstName;
547 userdata.LastName = uac.LastName;
548 userdata.HomeURL = string.Empty;
549 userdata.IsUnknownUser = false;
550 userdata.HasGridUserTried = true;
551 lock (m_UserCache)
552 m_UserCache[uac.PrincipalID] = userdata;
553 }
554 }
555 }
556
557 if (missing.Count == 0 || m_Scenes[0].GridUserService == null)
558 return ret;
559
560 // try grid user service
561
562 GridUserInfo[] pinfos = m_Scenes[0].GridUserService.GetGridUserInfo(missing.ToArray());
563 if(pinfos.Length > 0)
564 {
565 foreach(GridUserInfo uInfo in pinfos)
566 {
567 if (uInfo != null)
568 {
569 string url, first, last, tmp;
570
571 if(uInfo.UserID.Length <= 36)
572 continue;
573
574 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out uuid, out url, out first, out last, out tmp))
575 {
576 if (url != string.Empty)
577 {
578 try
579 {
580 userdata = new UserData();
581 userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
582 userdata.LastName = "@" + new Uri(url).Authority;
583 userdata.Id = uuid;
584 userdata.HomeURL = url;
585 userdata.IsUnknownUser = false;
586 userdata.HasGridUserTried = true;
587 lock (m_UserCache)
588 m_UserCache[uuid] = userdata;
589
590 string name = userdata.FirstName + " " + userdata.LastName;
591 ret[uuid] = name;
592 missing.Remove(uuid.ToString());
593 untried.Remove(uuid);
594 }
595 catch
596 {
597 }
598 }
599 }
600 }
601 }
602 }
603
604 // add the untried in cache that still failed
605 if(untried.Count > 0)
606 {
607 foreach(KeyValuePair<UUID, string> kvp in untried)
608 {
609 ret[kvp.Key] = kvp.Value;
610 missing.Remove((kvp.Key).ToString());
611 }
612 }
613
614 // add the UMMthings ( not sure we should)
615 if(missing.Count > 0)
616 {
617 foreach(string id in missing)
618 {
619 if(UUID.TryParse(id, out uuid) && uuid != UUID.Zero)
620 {
621 if (m_Scenes[0].LibraryService != null &&
622 (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
623 ret[uuid] = "Mr OpenSim";
624 else
625 ret[uuid] = "Unknown UserUMMAU43";
626 }
627 }
628 }
629
630 return ret;
631 }
632
633 public virtual string GetUserHomeURL(UUID userID)
378 { 634 {
379 UserData user; 635 UserData user;
380 if(GetUser(userID, out user)) 636 if(GetUser(userID, out user))
@@ -384,7 +640,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
384 return string.Empty; 640 return string.Empty;
385 } 641 }
386 642
387 public string GetUserServerURL(UUID userID, string serverType) 643 public virtual string GetUserServerURL(UUID userID, string serverType)
388 { 644 {
389 UserData userdata; 645 UserData userdata;
390 if(!GetUser(userID, out userdata)) 646 if(!GetUser(userID, out userdata))
@@ -424,14 +680,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
424 return string.Empty; 680 return string.Empty;
425 } 681 }
426 682
427 public string GetUserUUI(UUID userID) 683 public virtual string GetUserUUI(UUID userID)
428 { 684 {
429 string uui; 685 string uui;
430 GetUserUUI(userID, out uui); 686 GetUserUUI(userID, out uui);
431 return uui; 687 return uui;
432 } 688 }
433 689
434 public bool GetUserUUI(UUID userID, out string uui) 690 public virtual bool GetUserUUI(UUID userID, out string uui)
435 { 691 {
436 UserData ud; 692 UserData ud;
437 bool result = GetUser(userID, out ud); 693 bool result = GetUser(userID, out ud);
@@ -449,6 +705,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
449 last = parts[1]; 705 last = parts[1];
450 } 706 }
451 uui = userID + ";" + homeURL + ";" + first + " " + last; 707 uui = userID + ";" + homeURL + ";" + first + " " + last;
708 return result;
452 } 709 }
453 } 710 }
454 711
@@ -457,8 +714,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
457 } 714 }
458 715
459 #region Cache Management 716 #region Cache Management
460 public bool GetUser(UUID uuid, out UserData userdata) 717 public virtual bool GetUser(UUID uuid, out UserData userdata)
461 { 718 {
719 if(m_Scenes.Count <= 0)
720 {
721 userdata = new UserData();
722 return false;
723 }
724
462 lock (m_UserCache) 725 lock (m_UserCache)
463 { 726 {
464 if (m_UserCache.TryGetValue(uuid, out userdata)) 727 if (m_UserCache.TryGetValue(uuid, out userdata))
@@ -471,7 +734,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
471 else 734 else
472 { 735 {
473 userdata = new UserData(); 736 userdata = new UserData();
474 userdata.HasGridUserTried = false;
475 userdata.Id = uuid; 737 userdata.Id = uuid;
476 userdata.FirstName = "Unknown"; 738 userdata.FirstName = "Unknown";
477 userdata.LastName = "UserUMMAU42"; 739 userdata.LastName = "UserUMMAU42";
@@ -544,7 +806,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
544 return !userdata.IsUnknownUser; 806 return !userdata.IsUnknownUser;
545 } 807 }
546 808
547 public void AddUser(UUID uuid, string first, string last) 809 public virtual void AddUser(UUID uuid, string first, string last, bool isNPC = false)
548 { 810 {
549 lock(m_UserCache) 811 lock(m_UserCache)
550 { 812 {
@@ -555,13 +817,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
555 user.FirstName = first; 817 user.FirstName = first;
556 user.LastName = last; 818 user.LastName = last;
557 user.IsUnknownUser = false; 819 user.IsUnknownUser = false;
558 user.HasGridUserTried = false; 820 user.HasGridUserTried = isNPC;
559 m_UserCache.Add(uuid, user); 821 m_UserCache.Add(uuid, user);
560 } 822 }
561 } 823 }
562 } 824 }
563 825
564 public void AddUser(UUID uuid, string first, string last, string homeURL) 826 public virtual void AddUser(UUID uuid, string first, string last, string homeURL)
565 { 827 {
566 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); 828 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
567 829
@@ -611,7 +873,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
611 } 873 }
612 } 874 }
613 875
614 public void AddUser(UUID id, string creatorData) 876 public virtual void AddUser(UUID id, string creatorData)
615 { 877 {
616 // m_log.InfoFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); 878 // m_log.InfoFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
617 879
@@ -694,24 +956,29 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
694 } 956 }
695 #endregion 957 #endregion
696 958
697 public bool IsLocalGridUser(UUID uuid) 959 public virtual bool IsLocalGridUser(UUID uuid)
698 { 960 {
699 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid); 961 lock (m_Scenes)
700 if (account == null || (account != null && !account.LocalToGrid)) 962 {
701 return false; 963 if (m_Scenes.Count == 0)
964 return true;
965 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid);
966 if (account == null || (account != null && !account.LocalToGrid))
967 return false;
968 }
702 969
703 return true; 970 return true;
704 } 971 }
705 972
706 #endregion IUserManagement 973 #endregion IUserManagement
707 974
708 protected void Init() 975 protected virtual void Init()
709 { 976 {
710 AddUser(UUID.Zero, "Unknown", "User"); 977 AddUser(UUID.Zero, "Unknown", "User");
711 RegisterConsoleCmds(); 978 RegisterConsoleCmds();
712 } 979 }
713 980
714 protected void RegisterConsoleCmds() 981 protected virtual void RegisterConsoleCmds()
715 { 982 {
716 MainConsole.Instance.Commands.AddCommand("Users", true, 983 MainConsole.Instance.Commands.AddCommand("Users", true,
717 "show name", 984 "show name",
@@ -735,7 +1002,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
735 HandleResetUserCache); 1002 HandleResetUserCache);
736 } 1003 }
737 1004
738 private void HandleResetUserCache(string module, string[] cmd) 1005 protected virtual void HandleResetUserCache(string module, string[] cmd)
739 { 1006 {
740 lock(m_UserCache) 1007 lock(m_UserCache)
741 { 1008 {
@@ -743,7 +1010,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
743 } 1010 }
744 } 1011 }
745 1012
746 private void HandleShowUser(string module, string[] cmd) 1013 protected virtual void HandleShowUser(string module, string[] cmd)
747 { 1014 {
748 if (cmd.Length < 3) 1015 if (cmd.Length < 3)
749 { 1016 {
@@ -772,7 +1039,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
772 MainConsole.Instance.Output(cdt.ToString()); 1039 MainConsole.Instance.Output(cdt.ToString());
773 } 1040 }
774 1041
775 private void HandleShowUsers(string module, string[] cmd) 1042 protected virtual void HandleShowUsers(string module, string[] cmd)
776 { 1043 {
777 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 1044 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
778 cdt.AddColumn("UUID", 36); 1045 cdt.AddColumn("UUID", 36);
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index ea5b34e..8c44ee2 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -46,7 +46,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid
46 public class HGWorldMapModule : WorldMapModule 46 public class HGWorldMapModule : WorldMapModule
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 // Remember the map area that each client has been exposed to in this region 50 // Remember the map area that each client has been exposed to in this region
51 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>(); 51 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>();
52 52
@@ -106,6 +106,8 @@ namespace OpenSim.Region.CoreModules.Hypergrid
106 if (!m_Enabled) 106 if (!m_Enabled)
107 return; 107 return;
108 108
109 base.RemoveRegion(scene);
110
109 scene.EventManager.OnClientClosed -= EventManager_OnClientClosed; 111 scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
110 } 112 }
111 113
@@ -138,9 +140,9 @@ namespace OpenSim.Region.CoreModules.Hypergrid
138 } 140 }
139 } 141 }
140 142
141 protected override List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 143 protected override List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
142 { 144 {
143 List<MapBlockData> mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); 145 List<MapBlockData> mapBlocks = base.GetAndSendBlocksInternal(remoteClient, minX, minY, maxX, maxY, flag);
144 lock (m_SeenMapBlocks) 146 lock (m_SeenMapBlocks)
145 { 147 {
146 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) 148 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId))
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
index 63e3c92..2e3ac8e 100644
--- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
@@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices; 3using System.Runtime.InteropServices;
4using Mono.Addins; 4using Mono.Addins;
5 5
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.CoreModules")] 9[assembly: AssemblyTitle("OpenSim.Region.CoreModules")]
@@ -15,8 +15,8 @@ using Mono.Addins;
15[assembly: AssemblyTrademark("")] 15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")] 16[assembly: AssemblyCulture("")]
17 17
18// Setting ComVisible to false makes the types in this assembly not visible 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 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. 20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)] 21[assembly: ComVisible(false)]
22 22
@@ -26,11 +26,11 @@ using Mono.Addins;
26// Version information for an assembly consists of the following four values: 26// Version information for an assembly consists of the following four values:
27// 27//
28// Major Version 28// Major Version
29// Minor Version 29// Minor Version
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.8.3.*")] 33[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
34 34
35 35
36[assembly: Addin("OpenSim.Region.CoreModules", OpenSim.VersionInfo.VersionNumber)] 36[assembly: Addin("OpenSim.Region.CoreModules", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index a686a4d..090cb7d 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -135,17 +135,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
135 m_reuseableDynamicTextures.Store( 135 m_reuseableDynamicTextures.Store(
136 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); 136 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
137 } 137 }
138 updater.newTextureID = newTextureID;
138 } 139 }
139 }
140 140
141 if (updater.UpdateTimer == 0)
142 {
143 lock (Updaters) 141 lock (Updaters)
144 { 142 {
145 if (!Updaters.ContainsKey(updater.UpdaterID)) 143 if (Updaters.ContainsKey(updater.UpdaterID))
146 {
147 Updaters.Remove(updater.UpdaterID); 144 Updaters.Remove(updater.UpdaterID);
148 }
149 } 145 }
150 } 146 }
151 } 147 }
@@ -172,21 +168,20 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
172 } 168 }
173 169
174 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 170 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
175 string extraParams, int updateTimer) 171 string extraParams)
176 { 172 {
177 return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); 173 return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, false, 255);
178 } 174 }
179 175
180 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 176 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
181 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) 177 string extraParams, bool SetBlending, byte AlphaValue)
182 { 178 {
183 return AddDynamicTextureURL(simID, primID, contentType, url, 179 return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, SetBlending,
184 extraParams, updateTimer, SetBlending, 180 (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
185 (int)(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
186 } 181 }
187 182
188 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 183 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
189 string extraParams, int updateTimer, bool SetBlending, 184 string extraParams, bool SetBlending,
190 int disp, byte AlphaValue, int face) 185 int disp, byte AlphaValue, int face)
191 { 186 {
192 if (RenderPlugins.ContainsKey(contentType)) 187 if (RenderPlugins.ContainsKey(contentType))
@@ -196,7 +191,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
196 updater.PrimID = primID; 191 updater.PrimID = primID;
197 updater.ContentType = contentType; 192 updater.ContentType = contentType;
198 updater.Url = url; 193 updater.Url = url;
199 updater.UpdateTimer = updateTimer;
200 updater.UpdaterID = UUID.Random(); 194 updater.UpdaterID = UUID.Random();
201 updater.Params = extraParams; 195 updater.Params = extraParams;
202 updater.BlendWithOldTexture = SetBlending; 196 updater.BlendWithOldTexture = SetBlending;
@@ -213,26 +207,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
213 } 207 }
214 208
215 RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); 209 RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
216 return updater.UpdaterID; 210 return updater.newTextureID;
217 } 211 }
218 return UUID.Zero; 212 return UUID.Zero;
219 } 213 }
220 214
221 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 215 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
222 string extraParams, int updateTimer) 216 string extraParams)
223 { 217 {
224 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); 218 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, false,
219 (DISP_TEMP|DISP_EXPIRE), 255, ALL_SIDES);
225 } 220 }
226 221
227 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 222 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
228 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) 223 string extraParams, bool SetBlending, byte AlphaValue)
229 { 224 {
230 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, SetBlending, 225 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, SetBlending,
231 (int) (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); 226 (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
232 } 227 }
233 228
234 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 229 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
235 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) 230 string extraParams, bool SetBlending, int disp, byte AlphaValue, int face)
236 { 231 {
237 if (!RenderPlugins.ContainsKey(contentType)) 232 if (!RenderPlugins.ContainsKey(contentType))
238 return UUID.Zero; 233 return UUID.Zero;
@@ -258,7 +253,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
258 updater.PrimID = primID; 253 updater.PrimID = primID;
259 updater.ContentType = contentType; 254 updater.ContentType = contentType;
260 updater.BodyData = data; 255 updater.BodyData = data;
261 updater.UpdateTimer = updateTimer;
262 updater.UpdaterID = UUID.Random(); 256 updater.UpdaterID = UUID.Random();
263 updater.Params = extraParams; 257 updater.Params = extraParams;
264 updater.BlendWithOldTexture = SetBlending; 258 updater.BlendWithOldTexture = SetBlending;
@@ -314,7 +308,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
314 updater.UpdatePart(part, (UUID)objReusableTextureUUID); 308 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
315 } 309 }
316 310
317 return updater.UpdaterID; 311 return updater.newTextureID;
318 } 312 }
319 313
320 private string GenerateReusableTextureKey(string data, string extraParams) 314 private string GenerateReusableTextureKey(string data, string extraParams)
@@ -404,17 +398,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
404 public byte FrontAlpha = 255; 398 public byte FrontAlpha = 255;
405 public string Params; 399 public string Params;
406 public UUID PrimID; 400 public UUID PrimID;
407 public bool SetNewFrontAlpha = false;
408 public UUID SimUUID; 401 public UUID SimUUID;
409 public UUID UpdaterID; 402 public UUID UpdaterID;
410 public int UpdateTimer;
411 public int Face; 403 public int Face;
412 public int Disp; 404 public int Disp;
413 public string Url; 405 public string Url;
406 public UUID newTextureID;
414 407
415 public DynamicTextureUpdater() 408 public DynamicTextureUpdater()
416 { 409 {
417 UpdateTimer = 0;
418 BodyData = null; 410 BodyData = null;
419 } 411 }
420 412
@@ -436,16 +428,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
436 // FIXME: Need to return the appropriate ID if only a single face is replaced. 428 // FIXME: Need to return the appropriate ID if only a single face is replaced.
437 oldID = tmptex.DefaultTexture.TextureID; 429 oldID = tmptex.DefaultTexture.TextureID;
438 430
431 // not using parts number of faces because that fails on old meshs
439 if (Face == ALL_SIDES) 432 if (Face == ALL_SIDES)
440 { 433 {
441 oldID = tmptex.DefaultTexture.TextureID; 434 oldID = tmptex.DefaultTexture.TextureID;
442 tmptex.DefaultTexture.TextureID = textureID; 435 tmptex.DefaultTexture.TextureID = textureID;
436 for(int i = 0; i < tmptex.FaceTextures.Length; i++)
437 {
438 if(tmptex.FaceTextures[i] != null)
439 tmptex.FaceTextures[i].TextureID = textureID;
440 }
443 } 441 }
444 else 442 else
445 { 443 {
446 try 444 try
447 { 445 {
448 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); 446 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
447 oldID = texface.TextureID;
449 texface.TextureID = textureID; 448 texface.TextureID = textureID;
450 tmptex.FaceTextures[Face] = texface; 449 tmptex.FaceTextures[Face] = texface;
451 } 450 }
@@ -455,10 +454,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
455 } 454 }
456 } 455 }
457 456
458 // I'm pretty sure we always want to force this to true
459 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
460 // tmptex.DefaultTexture.Fullbright = true;
461
462 part.UpdateTextureEntry(tmptex.GetBytes()); 457 part.UpdateTextureEntry(tmptex.GetBytes());
463 } 458 }
464 459
@@ -478,26 +473,39 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
478 473
479 if (part == null || data == null || data.Length <= 1) 474 if (part == null || data == null || data.Length <= 1)
480 { 475 {
481 string msg = 476 string msg =
482 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 477 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
483 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 478 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
484 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 479 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
485 480
486 return UUID.Zero; 481 return UUID.Zero;
487 } 482 }
488 483
489 byte[] assetData = null; 484 byte[] assetData = null;
490 AssetBase oldAsset = null; 485 AssetBase oldAsset = null;
491 486
492 if (BlendWithOldTexture) 487 if (BlendWithOldTexture)
493 { 488 {
494 Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture; 489 Primitive.TextureEntryFace curFace;
495 if (defaultFace != null) 490 if(Face == ALL_SIDES)
491 curFace = part.Shape.Textures.DefaultTexture;
492 else
496 { 493 {
497 oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString()); 494 try
495 {
496 curFace = part.Shape.Textures.GetFace((uint)Face);
497 }
498 catch
499 {
500 curFace = null;
501 }
502 }
503 if (curFace != null)
504 {
505 oldAsset = scene.AssetService.Get(curFace.TextureID.ToString());
498 506
499 if (oldAsset != null) 507 if (oldAsset != null)
500 assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); 508 assetData = BlendTextures(data, oldAsset.Data, FrontAlpha);
501 } 509 }
502 } 510 }
503 511
@@ -548,42 +556,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
548 return asset.FullID; 556 return asset.FullID;
549 } 557 }
550 558
551 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 559 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, byte newAlpha)
552 { 560 {
553 ManagedImage managedImage; 561 ManagedImage managedImage;
554 Image image; 562 Image image;
555 563
556 if (OpenJPEG.DecodeToImage(frontImage, out managedImage, out image)) 564 if (!OpenJPEG.DecodeToImage(frontImage, out managedImage, out image) || image == null)
565 return null;
566
567 Bitmap image1 = new Bitmap(image);
568 image.Dispose();
569
570 if (!OpenJPEG.DecodeToImage(backImage, out managedImage, out image) || image == null)
557 { 571 {
558 Bitmap image1 = new Bitmap(image); 572 image1.Dispose();
573 return null;
574 }
559 575
560 if (OpenJPEG.DecodeToImage(backImage, out managedImage, out image)) 576 Bitmap image2 = new Bitmap(image);
561 { 577 image.Dispose();
562 Bitmap image2 = new Bitmap(image);
563 578
564 if (setNewAlpha) 579 if (newAlpha < 255)
565 SetAlpha(ref image1, newAlpha); 580 SetAlpha(ref image1, newAlpha);
566 581
567 Bitmap joint = MergeBitMaps(image1, image2); 582 using(Bitmap joint = MergeBitMaps(image1, image2))
583 {
584 image1.Dispose();
585 image2.Dispose();
568 586
569 byte[] result = new byte[0]; 587 byte[] result = new byte[0];
570 588
571 try 589 try
572 { 590 {
573 result = OpenJPEG.EncodeFromImage(joint, true); 591 result = OpenJPEG.EncodeFromImage(joint, true);
574 } 592 }
575 catch (Exception e) 593 catch (Exception e)
576 { 594 {
577 m_log.ErrorFormat( 595 m_log.ErrorFormat(
578 "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Exception {0}{1}", 596 "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
579 e.Message, e.StackTrace); 597 e.Message, e.StackTrace);
580 }
581
582 return result;
583 } 598 }
584 }
585 599
586 return null; 600 return result;
601 }
587 } 602 }
588 603
589 public Bitmap MergeBitMaps(Bitmap front, Bitmap back) 604 public Bitmap MergeBitMaps(Bitmap front, Bitmap back)
@@ -592,12 +607,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
592 Graphics jG; 607 Graphics jG;
593 608
594 joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb); 609 joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb);
595 jG = Graphics.FromImage(joint); 610 using(jG = Graphics.FromImage(joint))
596 611 {
597 jG.DrawImage(back, 0, 0, back.Width, back.Height); 612 jG.DrawImage(back, 0, 0, back.Width, back.Height);
598 jG.DrawImage(front, 0, 0, back.Width, back.Height); 613 jG.DrawImage(front, 0, 0, back.Width, back.Height);
599 614 return joint;
600 return joint; 615 }
601 } 616 }
602 617
603 private void SetAlpha(ref Bitmap b, byte alpha) 618 private void SetAlpha(ref Bitmap b, byte alpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
index 4e7ad75..d59cfa9 100644
--- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
@@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
113 } 113 }
114 catch (Exception e) 114 catch (Exception e)
115 { 115 {
116 m_log.Error("[EMAIL] DefaultEmailModule not configured: " + e.Message); 116 m_log.Error("[EMAIL]: DefaultEmailModule not configured: " + e.Message);
117 m_Enabled = false; 117 m_Enabled = false;
118 return; 118 return;
119 } 119 }
@@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
142 } 142 }
143 } 143 }
144 144
145 m_log.Info("[EMAIL] Activated DefaultEmailModule"); 145 m_log.Info("[EMAIL]: Activated DefaultEmailModule");
146 } 146 }
147 147
148 public void RemoveRegion(Scene scene) 148 public void RemoveRegion(Scene scene)
@@ -224,8 +224,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
224 return null; 224 return null;
225 } 225 }
226 226
227 private void resolveNamePositionRegionName(UUID objectID, out string ObjectName, out string ObjectAbsolutePosition, out string ObjectRegionName) 227 private bool resolveNamePositionRegionName(UUID objectID, out string ObjectName, out string ObjectAbsolutePosition, out string ObjectRegionName)
228 { 228 {
229 ObjectName = ObjectAbsolutePosition = ObjectRegionName = String.Empty;
229 string m_ObjectRegionName; 230 string m_ObjectRegionName;
230 int objectLocX; 231 int objectLocX;
231 int objectLocY; 232 int objectLocY;
@@ -239,15 +240,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
239 ObjectAbsolutePosition = "(" + objectLocX + ", " + objectLocY + ", " + objectLocZ + ")"; 240 ObjectAbsolutePosition = "(" + objectLocX + ", " + objectLocY + ", " + objectLocZ + ")";
240 ObjectName = part.Name; 241 ObjectName = part.Name;
241 ObjectRegionName = m_ObjectRegionName; 242 ObjectRegionName = m_ObjectRegionName;
242 return; 243 return true;
243 } 244 }
244 objectLocX = (int)part.AbsolutePosition.X; 245 return false;
245 objectLocY = (int)part.AbsolutePosition.Y;
246 objectLocZ = (int)part.AbsolutePosition.Z;
247 ObjectAbsolutePosition = "(" + objectLocX + ", " + objectLocY + ", " + objectLocZ + ")";
248 ObjectName = part.Name;
249 ObjectRegionName = m_ObjectRegionName;
250 return;
251 } 246 }
252 247
253 /// <summary> 248 /// <summary>
@@ -273,12 +268,12 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
273 bool isEMailStrictMatch = EMailreStrict.IsMatch(address); 268 bool isEMailStrictMatch = EMailreStrict.IsMatch(address);
274 if (!isEMailStrictMatch) 269 if (!isEMailStrictMatch)
275 { 270 {
276 m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); 271 m_log.Error("[EMAIL]: REGEX Problem in EMail Address: "+address);
277 return; 272 return;
278 } 273 }
279 if ((subject.Length + body.Length) > m_MaxEmailSize) 274 if ((subject.Length + body.Length) > m_MaxEmailSize)
280 { 275 {
281 m_log.Error("[EMAIL] subject + body larger than limit of " + m_MaxEmailSize + " bytes"); 276 m_log.Error("[EMAIL]: subject + body larger than limit of " + m_MaxEmailSize + " bytes");
282 return; 277 return;
283 } 278 }
284 279
@@ -286,7 +281,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
286 string LastObjectPosition = string.Empty; 281 string LastObjectPosition = string.Empty;
287 string LastObjectRegionName = string.Empty; 282 string LastObjectRegionName = string.Empty;
288 283
289 resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); 284 if (!resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName))
285 return;
290 286
291 if (!address.EndsWith(m_InterObjectHostname)) 287 if (!address.EndsWith(m_InterObjectHostname))
292 { 288 {
@@ -302,7 +298,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
302 //Subject 298 //Subject
303 emailMessage.Subject = subject; 299 emailMessage.Subject = subject;
304 //TEXT Body 300 //TEXT Body
305 resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); 301 if (!resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName))
302 return;
306 emailMessage.BodyText = "Object-Name: " + LastObjectName + 303 emailMessage.BodyText = "Object-Name: " + LastObjectName +
307 "\nRegion: " + LastObjectRegionName + "\nLocal-Position: " + 304 "\nRegion: " + LastObjectRegionName + "\nLocal-Position: " +
308 LastObjectPosition + "\n\n" + body; 305 LastObjectPosition + "\n\n" + body;
@@ -321,11 +318,11 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
321 emailMessage.Send(smtpServer); 318 emailMessage.Send(smtpServer);
322 319
323 //Log 320 //Log
324 m_log.Info("[EMAIL] EMail sent to: " + address + " from object: " + objectID.ToString() + "@" + m_HostName); 321 m_log.Info("[EMAIL]: EMail sent to: " + address + " from object: " + objectID.ToString() + "@" + m_HostName);
325 } 322 }
326 catch (Exception e) 323 catch (Exception e)
327 { 324 {
328 m_log.Error("[EMAIL] DefaultEmailModule Exception: " + e.Message); 325 m_log.Error("[EMAIL]: DefaultEmailModule Exception: " + e.Message);
329 } 326 }
330 } 327 }
331 else 328 else
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 9dfeb96..84b4707 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 {
@@ -191,7 +190,15 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
191 190
192 case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH: 191 case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH:
193 192
194 // TODO implement me 193 int len;
194 if(int.TryParse(parms[i + 1], out len))
195 {
196 if(len > HttpRequestClass.HttpBodyMaxLenMAX)
197 len = HttpRequestClass.HttpBodyMaxLenMAX;
198 else if(len < 64) //???
199 len = 64;
200 htc.HttpBodyMaxLen = len;
201 }
195 break; 202 break;
196 203
197 case (int)HttpRequestConstants.HTTP_VERIFY_CERT: 204 case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
@@ -216,20 +223,16 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
216 if (parms.Length - i < 2) 223 if (parms.Length - i < 2)
217 break; 224 break;
218 225
219 //Have we reached the end of the list of headers?
220 //End is marked by a string with a single digit.
221 //We already know we have at least one parameter
222 //so it is safe to do this check at top of loop.
223 if (Char.IsDigit(parms[i][0]))
224 break;
225
226 if (htc.HttpCustomHeaders == null) 226 if (htc.HttpCustomHeaders == null)
227 htc.HttpCustomHeaders = new List<string>(); 227 htc.HttpCustomHeaders = new List<string>();
228 228
229 htc.HttpCustomHeaders.Add(parms[i]); 229 htc.HttpCustomHeaders.Add(parms[i]);
230 htc.HttpCustomHeaders.Add(parms[i+1]); 230 htc.HttpCustomHeaders.Add(parms[i+1]);
231 int nexti = i + 2;
232 if (nexti >= parms.Length || Char.IsDigit(parms[nexti][0]))
233 break;
231 234
232 i += 2; 235 i = nexti;
233 } 236 }
234 break; 237 break;
235 238
@@ -239,7 +242,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
239 } 242 }
240 } 243 }
241 } 244 }
242 245
243 htc.RequestModule = this; 246 htc.RequestModule = this;
244 htc.LocalID = localID; 247 htc.LocalID = localID;
245 htc.ItemID = itemID; 248 htc.ItemID = itemID;
@@ -276,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
276 } 279 }
277 280
278 public bool StartHttpRequest(HttpRequestClass req) 281 public bool StartHttpRequest(HttpRequestClass req)
279 { 282 {
280 if (!CheckAllowed(new Uri(req.Url))) 283 if (!CheckAllowed(new Uri(req.Url)))
281 return false; 284 return false;
282 285
@@ -290,29 +293,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
290 return true; 293 return true;
291 } 294 }
292 295
293 public void StopHttpRequestsForScript(UUID id) 296 public void StopHttpRequest(uint m_localID, UUID m_itemID)
294 { 297 {
295 if (m_pendingRequests != null) 298 if (m_pendingRequests != null)
296 { 299 {
297 List<UUID> keysToRemove = null;
298
299 lock (HttpListLock) 300 lock (HttpListLock)
300 { 301 {
301 foreach (HttpRequestClass req in m_pendingRequests.Values) 302 HttpRequestClass tmpReq;
303 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
302 { 304 {
303 if (req.ItemID == id) 305 tmpReq.Stop();
304 { 306 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 } 307 }
313
314 if (keysToRemove != null)
315 keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove));
316 } 308 }
317 } 309 }
318 } 310 }
@@ -330,13 +322,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
330 { 322 {
331 lock (HttpListLock) 323 lock (HttpListLock)
332 { 324 {
333 foreach (HttpRequestClass req in m_pendingRequests.Values) 325 foreach (UUID luid in m_pendingRequests.Keys)
334 { 326 {
335 if (req.Finished) 327 HttpRequestClass tmpReq;
336 return req; 328
329 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
330 {
331 if (tmpReq.Finished)
332 {
333 return tmpReq;
334 }
335 }
337 } 336 }
338 } 337 }
339
340 return null; 338 return null;
341 } 339 }
342 340
@@ -363,9 +361,34 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
363 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 361 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
364 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 362 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
365 363
364 HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384);
365
366
366 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); 367 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
368 int maxThreads = 15;
369
370 IConfig httpConfig = config.Configs["HttpRequestModule"];
371 if (httpConfig != null)
372 {
373 maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
374 }
367 375
368 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 376 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
377
378 // First instance sets this up for all sims
379 if (ThreadPool == null)
380 {
381 STPStartInfo startInfo = new STPStartInfo();
382 startInfo.IdleTimeout = 2000;
383 startInfo.MaxWorkerThreads = maxThreads;
384 startInfo.MinWorkerThreads = 0;
385 startInfo.ThreadPriority = ThreadPriority.BelowNormal;
386 startInfo.StartSuspended = true;
387 startInfo.ThreadPoolName = "ScriptsHttpReq";
388
389 ThreadPool = new SmartThreadPool(startInfo);
390 ThreadPool.Start();
391 }
369 } 392 }
370 393
371 public void AddRegion(Scene scene) 394 public void AddRegion(Scene scene)
@@ -392,6 +415,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
392 415
393 public void Close() 416 public void Close()
394 { 417 {
418 ThreadPool.Shutdown();
395 } 419 }
396 420
397 public string Name 421 public string Name
@@ -409,8 +433,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
409 433
410 public class HttpRequestClass : IServiceRequest 434 public class HttpRequestClass : IServiceRequest
411 { 435 {
412// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
413
414 // Constants for parameters 436 // Constants for parameters
415 // public const int HTTP_BODY_MAXLENGTH = 2; 437 // public const int HTTP_BODY_MAXLENGTH = 2;
416 // public const int HTTP_METHOD = 0; 438 // public const int HTTP_METHOD = 0;
@@ -430,13 +452,17 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
430 { 452 {
431 get { return _finished; } 453 get { return _finished; }
432 } 454 }
433 // public int HttpBodyMaxLen = 2048; // not implemented 455
456 public static int HttpBodyMaxLenMAX = 16384;
434 457
435 // Parameter members and default values 458 // Parameter members and default values
459 public int HttpBodyMaxLen = 2048;
436 public string HttpMethod = "GET"; 460 public string HttpMethod = "GET";
437 public string HttpMIMEType = "text/plain;charset=utf-8"; 461 public string HttpMIMEType = "text/plain;charset=utf-8";
438 public int HttpTimeout; 462 public int HttpTimeout;
439 public bool HttpVerifyCert = true; 463 public bool HttpVerifyCert = true;
464 public IWorkItemResult WorkItem = null;
465
440 //public bool HttpVerboseThrottle = true; // not implemented 466 //public bool HttpVerboseThrottle = true; // not implemented
441 public List<string> HttpCustomHeaders = null; 467 public List<string> HttpCustomHeaders = null;
442 public bool HttpPragmaNoCache = true; 468 public bool HttpPragmaNoCache = true;
@@ -484,15 +510,40 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
484 510
485 public void Process() 511 public void Process()
486 { 512 {
513 _finished = false;
514
515 lock (HttpRequestModule.ThreadPool)
516 WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
517 }
518
519 private object StpSendWrapper(object o)
520 {
487 SendRequest(); 521 SendRequest();
522 return null;
488 } 523 }
489 524
525 /*
526 * TODO: More work on the response codes. Right now
527 * returning 200 for success or 499 for exception
528 */
529
490 public void SendRequest() 530 public void SendRequest()
491 { 531 {
532 HttpWebResponse response = null;
533 Stream resStream = null;
534 byte[] buf = new byte[HttpBodyMaxLenMAX + 16];
535 string tempString = null;
536 int count = 0;
537
492 try 538 try
493 { 539 {
494 Request = (HttpWebRequest)WebRequest.Create(Url); 540 Request = (HttpWebRequest)WebRequest.Create(Url);
495 Request.AllowAutoRedirect = false; 541 Request.AllowAutoRedirect = false;
542 Request.KeepAlive = false;
543
544 //This works around some buggy HTTP Servers like Lighttpd
545 Request.ServicePoint.Expect100Continue = false;
546
496 Request.Method = HttpMethod; 547 Request.Method = HttpMethod;
497 Request.ContentType = HttpMIMEType; 548 Request.ContentType = HttpMIMEType;
498 549
@@ -500,7 +551,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
500 { 551 {
501 // We could hijack Connection Group Name to identify 552 // We could hijack Connection Group Name to identify
502 // a desired security exception. But at the moment we'll use a dummy header instead. 553 // 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"); 554 Request.Headers.Add("NoVerifyCert", "true");
505 } 555 }
506// else 556// else
@@ -533,14 +583,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
533 } 583 }
534 } 584 }
535 585
536 if (ResponseHeaders != null) 586 foreach (KeyValuePair<string, string> entry in ResponseHeaders)
537 { 587 if (entry.Key.ToLower().Equals("user-agent"))
538 foreach (KeyValuePair<string, string> entry in ResponseHeaders) 588 Request.UserAgent = entry.Value;
539 if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest) 589 else
540 ((HttpWebRequest)Request).UserAgent = entry.Value; 590 Request.Headers[entry.Key] = entry.Value;
541 else
542 Request.Headers[entry.Key] = entry.Value;
543 }
544 591
545 // Encode outbound data 592 // Encode outbound data
546 if (!string.IsNullOrEmpty(OutboundBody)) 593 if (!string.IsNullOrEmpty(OutboundBody))
@@ -552,12 +599,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
552 bstream.Write(data, 0, data.Length); 599 bstream.Write(data, 0, data.Length);
553 } 600 }
554 601
602 Request.Timeout = HttpTimeout;
555 try 603 try
556 { 604 {
557 IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); 605 // execute the request
558 606 response = (HttpWebResponse) Request.GetResponse();
559 ThreadPool.RegisterWaitForSingleObject(
560 result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true);
561 } 607 }
562 catch (WebException e) 608 catch (WebException e)
563 { 609 {
@@ -565,67 +611,74 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
565 { 611 {
566 throw; 612 throw;
567 } 613 }
614 response = (HttpWebResponse)e.Response;
615 }
568 616
569 HttpWebResponse response = (HttpWebResponse)e.Response; 617 Status = (int)response.StatusCode;
570 618
571 Status = (int)response.StatusCode; 619 resStream = response.GetResponseStream();
572 ResponseBody = response.StatusDescription; 620 int totalBodyBytes = 0;
573 _finished = true; 621 int maxBytes = HttpBodyMaxLen;
574 } 622 if(maxBytes > buf.Length)
575 } 623 maxBytes = buf.Length;
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 624
581 Status = (int)OSHttpStatusCode.ClientErrorJoker; 625 // we need to read all allowed or UFT8 conversion may fail
582 ResponseBody = e.Message; 626 do
583 _finished = true; 627 {
584 } 628 // fill the buffer with data
585 } 629 count = resStream.Read(buf, totalBodyBytes, maxBytes - totalBodyBytes);
630 totalBodyBytes += count;
631 if (totalBodyBytes >= maxBytes)
632 break;
586 633
587 private void ResponseCallback(IAsyncResult ar) 634 } while (count > 0); // any more data to read?
588 {
589 HttpWebResponse response = null;
590 635
591 try 636 if(totalBodyBytes > 0)
592 {
593 try
594 { 637 {
595 response = (HttpWebResponse)Request.EndGetResponse(ar); 638 tempString = Util.UTF8.GetString(buf, 0, totalBodyBytes);
639 ResponseBody = tempString.Replace("\r", "");
596 } 640 }
597 catch (WebException e) 641 else
642 ResponseBody = "";
643 }
644 catch (WebException e)
645 {
646 if (e.Status == WebExceptionStatus.ProtocolError)
598 { 647 {
599 if (e.Status != WebExceptionStatus.ProtocolError) 648 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
649 Status = (int)webRsp.StatusCode;
650 try
600 { 651 {
601 throw; 652 using (Stream responseStream = webRsp.GetResponseStream())
653 {
654 using (StreamReader reader = new StreamReader(responseStream))
655 ResponseBody = reader.ReadToEnd();
656 }
657 }
658 catch
659 {
660 ResponseBody = webRsp.StatusDescription;
602 } 661 }
603
604 response = (HttpWebResponse)e.Response;
605 } 662 }
606 663 else
607 Status = (int)response.StatusCode;
608
609 using (Stream stream = response.GetResponseStream())
610 { 664 {
611 StreamReader reader = new StreamReader(stream, Encoding.UTF8); 665 Status = (int)OSHttpStatusCode.ClientErrorJoker;
612 ResponseBody = reader.ReadToEnd(); 666 ResponseBody = e.Message;
613 } 667 }
614 } 668 }
615 catch (Exception e) 669 catch (Exception)
616 { 670 {
617 Status = (int)OSHttpStatusCode.ClientErrorJoker; 671 // 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 } 672 }
623 finally 673 finally
624 { 674 {
675 if (resStream != null)
676 resStream.Close();
625 if (response != null) 677 if (response != null)
626 response.Close(); 678 response.Close();
627 679
628 // We need to resubmit 680
681 // We need to resubmit
629 if ( 682 if (
630 (Status == (int)HttpStatusCode.MovedPermanently 683 (Status == (int)HttpStatusCode.MovedPermanently
631 || Status == (int)HttpStatusCode.Found 684 || Status == (int)HttpStatusCode.Found
@@ -670,22 +723,24 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
670 else 723 else
671 { 724 {
672 _finished = true; 725 _finished = true;
726 if (ResponseBody == null)
727 ResponseBody = String.Empty;
673 } 728 }
674 } 729 }
675 } 730 }
676 731
677 private void TimeoutCallback(object state, bool timedOut)
678 {
679 if (timedOut)
680 Request.Abort();
681 }
682
683 public void Stop() 732 public void Stop()
684 { 733 {
685// m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); 734 try
686 735 {
687 if (Request != null) 736 if (!WorkItem.Cancel())
688 Request.Abort(); 737 {
738 WorkItem.Cancel(true);
739 }
740 }
741 catch (Exception)
742 {
743 }
689 } 744 }
690 } 745 }
691} \ No newline at end of file 746}
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
index d22487e..7e223d7 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
@@ -45,7 +45,7 @@ using OpenSim.Tests.Common;
45namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests 45namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
46{ 46{
47 class TestWebRequestCreate : IWebRequestCreate 47 class TestWebRequestCreate : IWebRequestCreate
48 { 48 {
49 public TestWebRequest NextRequest { get; set; } 49 public TestWebRequest NextRequest { get; set; }
50 50
51 public WebRequest Create(Uri uri) 51 public WebRequest Create(Uri uri)
@@ -65,13 +65,13 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
65 65
66 public Func<IAsyncResult, WebResponse> OnEndGetResponse { get; set; } 66 public Func<IAsyncResult, WebResponse> OnEndGetResponse { get; set; }
67 67
68 public TestWebRequest() : base() 68 public TestWebRequest() : base()
69 { 69 {
70// Console.WriteLine("created"); 70// Console.WriteLine("created");
71 } 71 }
72 72
73// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) 73// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext)
74// : base(serializationInfo, streamingContext) 74// : base(serializationInfo, streamingContext)
75// { 75// {
76// Console.WriteLine("created"); 76// Console.WriteLine("created");
77// } 77// }
@@ -97,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
97 public string Response { get; set; } 97 public string Response { get; set; }
98 98
99#pragma warning disable 0618 99#pragma warning disable 0618
100 public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) 100 public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext)
101 : base(serializationInfo, streamingContext) {} 101 : base(serializationInfo, streamingContext) {}
102#pragma warning restore 0618 102#pragma warning restore 0618
103 103
@@ -111,24 +111,24 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
111 { 111 {
112 WaitHandle m_wh = new ManualResetEvent(true); 112 WaitHandle m_wh = new ManualResetEvent(true);
113 113
114 object IAsyncResult.AsyncState 114 object IAsyncResult.AsyncState
115 { 115 {
116 get { 116 get {
117 throw new System.NotImplementedException (); 117 throw new System.NotImplementedException ();
118 } 118 }
119 } 119 }
120 120
121 WaitHandle IAsyncResult.AsyncWaitHandle 121 WaitHandle IAsyncResult.AsyncWaitHandle
122 { 122 {
123 get { return m_wh; } 123 get { return m_wh; }
124 } 124 }
125 125
126 bool IAsyncResult.CompletedSynchronously 126 bool IAsyncResult.CompletedSynchronously
127 { 127 {
128 get { return false; } 128 get { return false; }
129 } 129 }
130 130
131 bool IAsyncResult.IsCompleted 131 bool IAsyncResult.IsCompleted
132 { 132 {
133 get { return true; } 133 get { return true; }
134 } 134 }
@@ -155,7 +155,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
155 TestHelpers.EnableLogging(); 155 TestHelpers.EnableLogging();
156 156
157 if (!Util.IsPlatformMono) 157 if (!Util.IsPlatformMono)
158 Assert.Ignore("Ignoring test since can only currently run on Mono"); 158 Assert.Ignore("Ignoring test since can only currently run on Mono");
159 159
160 string rawResponse = "boom"; 160 string rawResponse = "boom";
161 161
@@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
163 163
164 TestWebRequest twr = new TestWebRequest(); 164 TestWebRequest twr = new TestWebRequest();
165 //twr.OnEndGetResponse += ar => new TestHttpWebResponse(null, new StreamingContext()); 165 //twr.OnEndGetResponse += ar => new TestHttpWebResponse(null, new StreamingContext());
166 twr.OnEndGetResponse += ar => 166 twr.OnEndGetResponse += ar =>
167 { 167 {
168 SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new FormatterConverter()); 168 SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new FormatterConverter());
169 StreamingContext sc = new StreamingContext(); 169 StreamingContext sc = new StreamingContext();
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 99a3122..11fc513 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -26,10 +26,11 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
30using System.Collections.Generic; 29using System.Collections.Generic;
31using System.Collections; 30using System.Collections;
32using System.Reflection; 31using System.Reflection;
32using System.Net;
33using System.Net.Sockets;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
@@ -42,40 +43,17 @@ using OpenSim.Region.Framework.Scenes;
42 43
43namespace OpenSim.Region.CoreModules.Scripting.LSLHttp 44namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
44{ 45{
45 /// <summary>
46 /// Data describing an external URL set up by a script.
47 /// </summary>
48 public class UrlData 46 public class UrlData
49 { 47 {
50 /// <summary>
51 /// Scene object part hosting the script
52 /// </summary>
53 public UUID hostID; 48 public UUID hostID;
54
55 /// <summary>
56 /// The item ID of the script that requested the URL.
57 /// </summary>
58 public UUID itemID; 49 public UUID itemID;
59
60 /// <summary>
61 /// The script engine that runs the script.
62 /// </summary>
63 public IScriptModule engine; 50 public IScriptModule engine;
64
65 /// <summary>
66 /// The generated URL.
67 /// </summary>
68 public string url; 51 public string url;
69
70 /// <summary>
71 /// The random UUID component of the generated URL.
72 /// </summary>
73 public UUID urlcode; 52 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; 53 public Dictionary<UUID, RequestData> requests;
54 public bool isSsl;
55 public Scene scene;
56 public bool allowXss;
79 } 57 }
80 58
81 public class RequestData 59 public class RequestData
@@ -89,7 +67,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
89 //public ManualResetEvent ev; 67 //public ManualResetEvent ev;
90 public bool requestDone; 68 public bool requestDone;
91 public int startTime; 69 public int startTime;
70 public bool responseSent;
92 public string uri; 71 public string uri;
72 public bool allowResponseType = false;
73 public UUID hostID;
74 public Scene scene;
93 } 75 }
94 76
95 /// <summary> 77 /// <summary>
@@ -102,40 +84,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
102 LogManager.GetLogger( 84 LogManager.GetLogger(
103 MethodBase.GetCurrentMethod().DeclaringType); 85 MethodBase.GetCurrentMethod().DeclaringType);
104 86
105 /// <summary> 87 protected Dictionary<UUID, UrlData> m_RequestMap =
106 /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID 88 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 89
115 /// <summary> 90 protected Dictionary<string, UrlData> m_UrlMap =
116 /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL 91 new Dictionary<string, UrlData>();
117 /// </summary>
118 private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>();
119 92
120 private uint m_HttpsPort = 0; 93 protected bool m_enabled = false;
121 private IHttpServer m_HttpServer = null; 94 protected string m_ErrorStr;
122 private IHttpServer m_HttpsServer = null; 95 protected uint m_HttpsPort = 0;
96 protected IHttpServer m_HttpServer = null;
97 protected IHttpServer m_HttpsServer = null;
123 98
124 public string ExternalHostNameForLSL { get; private set; } 99 public string ExternalHostNameForLSL { get; protected set; }
125 100
126 /// <summary> 101 /// <summary>
127 /// The default maximum number of urls 102 /// The default maximum number of urls
128 /// </summary> 103 /// </summary>
129 public const int DefaultTotalUrls = 100; 104 public const int DefaultTotalUrls = 15000;
130 105
131 /// <summary> 106 /// <summary>
132 /// Maximum number of external urls that can be set up by this module. 107 /// Maximum number of external urls that can be set up by this module.
133 /// </summary> 108 /// </summary>
134 public int TotalUrls { get; set; } 109 public int TotalUrls { get; set; }
135 110
136 public Type ReplaceableInterface 111 public Type ReplaceableInterface
137 { 112 {
138 get { return null; } 113 get { return typeof(IUrlModule); }
139 } 114 }
140 115
141 public string Name 116 public string Name
@@ -146,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
146 public void Initialise(IConfigSource config) 121 public void Initialise(IConfigSource config)
147 { 122 {
148 IConfig networkConfig = config.Configs["Network"]; 123 IConfig networkConfig = config.Configs["Network"];
124 m_enabled = false;
149 125
150 if (networkConfig != null) 126 if (networkConfig != null)
151 { 127 {
@@ -156,9 +132,31 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
156 if (ssl_enabled) 132 if (ssl_enabled)
157 m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort); 133 m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort);
158 } 134 }
135 else
136 {
137 m_ErrorStr = "[Network] configuration missing, HTTP listener for LSL disabled";
138 m_log.Warn("[URL MODULE]: " + m_ErrorStr);
139 return;
140 }
159 141
160 if (ExternalHostNameForLSL == null) 142 if (String.IsNullOrWhiteSpace(ExternalHostNameForLSL))
161 ExternalHostNameForLSL = System.Environment.MachineName; 143 {
144 m_ErrorStr = "ExternalHostNameForLSL not defined in configuration, HTTP listener for LSL disabled";
145 m_log.Warn("[URL MODULE]: " + m_ErrorStr);
146 return;
147 }
148
149 IPAddress ia = null;
150 ia = Util.GetHostFromDNS(ExternalHostNameForLSL);
151 if (ia == null)
152 {
153 m_ErrorStr = "Could not resolve ExternalHostNameForLSL, HTTP listener for LSL disabled";
154 m_log.Warn("[URL MODULE]: " + m_ErrorStr);
155 return;
156 }
157
158 m_enabled = true;
159 m_ErrorStr = String.Empty;
162 160
163 IConfig llFunctionsConfig = config.Configs["LL-Functions"]; 161 IConfig llFunctionsConfig = config.Configs["LL-Functions"];
164 162
@@ -174,7 +172,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
174 172
175 public void AddRegion(Scene scene) 173 public void AddRegion(Scene scene)
176 { 174 {
177 if (m_HttpServer == null) 175 if (m_enabled && m_HttpServer == null)
178 { 176 {
179 // There can only be one 177 // There can only be one
180 // 178 //
@@ -204,21 +202,39 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
204 202
205 public void RemoveRegion(Scene scene) 203 public void RemoveRegion(Scene scene)
206 { 204 {
205 // Drop references to that scene
206 foreach (KeyValuePair<string, UrlData> kvp in m_UrlMap)
207 {
208 if (kvp.Value.scene == scene)
209 kvp.Value.scene = null;
210 }
211 foreach (KeyValuePair<UUID, UrlData> kvp in m_RequestMap)
212 {
213 if (kvp.Value.scene == scene)
214 kvp.Value.scene = null;
215 }
207 } 216 }
208 217
209 public void Close() 218 public void Close()
210 { 219 {
211 } 220 }
212 221
213 public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID) 222 public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options)
214 { 223 {
215 UUID urlcode = UUID.Random(); 224 UUID urlcode = UUID.Random();
216 225
226 if(!m_enabled)
227 {
228 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr });
229 return urlcode;
230 }
231
217 lock (m_UrlMap) 232 lock (m_UrlMap)
218 { 233 {
219 if (m_UrlMap.Count >= TotalUrls) 234 if (m_UrlMap.Count >= TotalUrls)
220 { 235 {
221 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 236 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED",
237 "Too many URLs already open" });
222 return urlcode; 238 return urlcode;
223 } 239 }
224 string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; 240 string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/";
@@ -229,20 +245,26 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
229 urlData.engine = engine; 245 urlData.engine = engine;
230 urlData.url = url; 246 urlData.url = url;
231 urlData.urlcode = urlcode; 247 urlData.urlcode = urlcode;
248 urlData.isSsl = false;
232 urlData.requests = new Dictionary<UUID, RequestData>(); 249 urlData.requests = new Dictionary<UUID, RequestData>();
233 250 urlData.scene = host.ParentGroup.Scene;
251 urlData.allowXss = false;
252
253 if (options != null && options["allowXss"] != null)
254 urlData.allowXss = true;
255
234 m_UrlMap[url] = urlData; 256 m_UrlMap[url] = urlData;
235 257
236 string uri = "/lslhttp/" + urlcode.ToString() + "/"; 258 string uri = "/lslhttp/" + urlcode.ToString() + "/";
237 259
238 PollServiceEventArgs args 260 PollServiceEventArgs args
239 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); 261 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
240 args.Type = PollServiceEventArgs.EventType.LslHttp; 262 args.Type = PollServiceEventArgs.EventType.LslHttp;
241 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 263 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
242 264
243 m_log.DebugFormat( 265// m_log.DebugFormat(
244 "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", 266// "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}",
245 uri, itemID, host.Name, host.LocalId); 267// uri, itemID, host.Name, host.LocalId);
246 268
247 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 269 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
248 } 270 }
@@ -250,10 +272,16 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
250 return urlcode; 272 return urlcode;
251 } 273 }
252 274
253 public UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID) 275 public UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options)
254 { 276 {
255 UUID urlcode = UUID.Random(); 277 UUID urlcode = UUID.Random();
256 278
279 if(!m_enabled)
280 {
281 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr });
282 return urlcode;
283 }
284
257 if (m_HttpsServer == null) 285 if (m_HttpsServer == null)
258 { 286 {
259 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 287 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" });
@@ -264,7 +292,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
264 { 292 {
265 if (m_UrlMap.Count >= TotalUrls) 293 if (m_UrlMap.Count >= TotalUrls)
266 { 294 {
267 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 295 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED",
296 "Too many URLs already open" });
268 return urlcode; 297 return urlcode;
269 } 298 }
270 string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; 299 string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/";
@@ -275,20 +304,25 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
275 urlData.engine = engine; 304 urlData.engine = engine;
276 urlData.url = url; 305 urlData.url = url;
277 urlData.urlcode = urlcode; 306 urlData.urlcode = urlcode;
307 urlData.isSsl = true;
278 urlData.requests = new Dictionary<UUID, RequestData>(); 308 urlData.requests = new Dictionary<UUID, RequestData>();
309 urlData.allowXss = false;
310
311 if (options != null && options["allowXss"] != null)
312 urlData.allowXss = true;
279 313
280 m_UrlMap[url] = urlData; 314 m_UrlMap[url] = urlData;
281 315
282 string uri = "/lslhttps/" + urlcode.ToString() + "/"; 316 string uri = "/lslhttps/" + urlcode.ToString() + "/";
283 317
284 PollServiceEventArgs args 318 PollServiceEventArgs args
285 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); 319 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
286 args.Type = PollServiceEventArgs.EventType.LslHttp; 320 args.Type = PollServiceEventArgs.EventType.LslHttp;
287 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 321 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
288 322
289 m_log.DebugFormat( 323// m_log.DebugFormat(
290 "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", 324// "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}",
291 uri, itemID, host.Name, host.LocalId); 325// uri, itemID, host.Name, host.LocalId);
292 326
293 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 327 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
294 } 328 }
@@ -307,18 +341,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
307 return; 341 return;
308 } 342 }
309 343
310 foreach (UUID req in data.requests.Keys) 344 lock (m_RequestMap)
311 m_RequestMap.Remove(req); 345 {
346 foreach (UUID req in data.requests.Keys)
347 m_RequestMap.Remove(req);
348 }
312 349
313 m_log.DebugFormat( 350// m_log.DebugFormat(
314 "[URL MODULE]: Releasing url {0} for {1} in {2}", 351// "[URL MODULE]: Releasing url {0} for {1} in {2}",
315 url, data.itemID, data.hostID); 352// url, data.itemID, data.hostID);
316 353
317 RemoveUrl(data); 354 RemoveUrl(data);
318 m_UrlMap.Remove(url); 355 m_UrlMap.Remove(url);
319 } 356 }
320 } 357 }
321 358
322 public void HttpContentType(UUID request, string type) 359 public void HttpContentType(UUID request, string type)
323 { 360 {
324 lock (m_UrlMap) 361 lock (m_UrlMap)
@@ -334,32 +371,42 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
334 } 371 }
335 } 372 }
336 } 373 }
337 374
338 public void HttpResponse(UUID request, int status, string body) 375 public void HttpResponse(UUID request, int status, string body)
339 { 376 {
340 lock (m_UrlMap) 377 lock (m_RequestMap)
341 { 378 {
342 if (m_RequestMap.ContainsKey(request)) 379 if (m_RequestMap.ContainsKey(request))
343 { 380 {
344 UrlData urlData = m_RequestMap[request]; 381 UrlData urlData = m_RequestMap[request];
345 string responseBody = body; 382 if (!urlData.requests[request].responseSent)
346 if (urlData.requests[request].responseType.Equals("text/plain"))
347 { 383 {
348 string value; 384 string responseBody = body;
349 if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) 385
386 // If we have no OpenID from built-in browser, disable this
387 if (!urlData.requests[request].allowResponseType)
388 urlData.requests[request].responseType = "text/plain";
389
390 if (urlData.requests[request].responseType.Equals("text/plain"))
350 { 391 {
351 if (value != null && value.IndexOf("MSIE") >= 0) 392 string value;
393 if (urlData.requests[request].headers.TryGetValue("user-agent", out value))
352 { 394 {
353 // wrap the html escaped response if the target client is IE 395 if (value != null && value.IndexOf("MSIE") >= 0)
354 // It ignores "text/plain" if the body is html 396 {
355 responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; 397 // wrap the html escaped response if the target client is IE
398 // It ignores "text/plain" if the body is html
399 responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>";
400 }
356 } 401 }
357 } 402 }
403
404 urlData.requests[request].responseCode = status;
405 urlData.requests[request].responseBody = responseBody;
406 //urlData.requests[request].ev.Set();
407 urlData.requests[request].requestDone = true;
408 urlData.requests[request].responseSent = true;
358 } 409 }
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 } 410 }
364 else 411 else
365 { 412 {
@@ -370,7 +417,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
370 417
371 public string GetHttpHeader(UUID requestId, string header) 418 public string GetHttpHeader(UUID requestId, string header)
372 { 419 {
373 lock (m_UrlMap) 420 lock (m_RequestMap)
374 { 421 {
375 if (m_RequestMap.ContainsKey(requestId)) 422 if (m_RequestMap.ContainsKey(requestId))
376 { 423 {
@@ -384,7 +431,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
384 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); 431 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
385 } 432 }
386 } 433 }
387
388 return String.Empty; 434 return String.Empty;
389 } 435 }
390 436
@@ -397,7 +443,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
397 public void ScriptRemoved(UUID itemID) 443 public void ScriptRemoved(UUID itemID)
398 { 444 {
399// m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID); 445// m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID);
400 446
401 lock (m_UrlMap) 447 lock (m_UrlMap)
402 { 448 {
403 List<string> removeURLs = new List<string>(); 449 List<string> removeURLs = new List<string>();
@@ -408,8 +454,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
408 { 454 {
409 RemoveUrl(url.Value); 455 RemoveUrl(url.Value);
410 removeURLs.Add(url.Key); 456 removeURLs.Add(url.Key);
411 foreach (UUID req in url.Value.requests.Keys) 457 lock (m_RequestMap)
412 m_RequestMap.Remove(req); 458 {
459 foreach (UUID req in url.Value.requests.Keys)
460 m_RequestMap.Remove(req);
461 }
413 } 462 }
414 } 463 }
415 464
@@ -430,9 +479,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
430 { 479 {
431 RemoveUrl(url.Value); 480 RemoveUrl(url.Value);
432 removeURLs.Add(url.Key); 481 removeURLs.Add(url.Key);
433 482 lock (m_RequestMap)
434 foreach (UUID req in url.Value.requests.Keys) 483 {
435 m_RequestMap.Remove(req); 484 foreach (UUID req in url.Value.requests.Keys)
485 m_RequestMap.Remove(req);
486 }
436 } 487 }
437 } 488 }
438 489
@@ -441,123 +492,131 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
441 } 492 }
442 } 493 }
443 494
444 private void RemoveUrl(UrlData data) 495
496 protected void RemoveUrl(UrlData data)
445 { 497 {
446 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/"); 498 if (data.isSsl)
499 m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/");
500 else
501 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
447 } 502 }
448 503
449 private Hashtable NoEvents(UUID requestID, UUID sessionID) 504 protected Hashtable NoEvents(UUID requestID, UUID sessionID)
450 { 505 {
451 Hashtable response = new Hashtable(); 506 Hashtable response = new Hashtable();
452 UrlData urlData; 507 UrlData url;
453 508 int startTime = 0;
454 lock (m_UrlMap) 509 lock (m_RequestMap)
455 { 510 {
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)) 511 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; 512 return response;
467 } 513 url = m_RequestMap[requestID];
514 startTime = url.requests[requestID].startTime;
515 }
468 516
469 urlData = m_RequestMap[requestID]; 517 if (System.Environment.TickCount - startTime > 25000)
518 {
519 response["int_response_code"] = 500;
520 response["str_response_string"] = "Script timeout";
521 response["content_type"] = "text/plain";
522 response["keepalive"] = false;
523 response["reusecontext"] = false;
470 524
471 if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) 525 //remove from map
526 lock (url.requests)
527 {
528 url.requests.Remove(requestID);
529 }
530 lock (m_RequestMap)
472 { 531 {
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); 532 m_RequestMap.Remove(requestID);
482
483 return response;
484 } 533 }
534
535 return response;
485 } 536 }
486 537
538
487 return response; 539 return response;
488 } 540 }
489 541
490 private bool HasEvents(UUID requestID, UUID sessionID) 542 protected bool HasEvents(UUID requestID, UUID sessionID)
491 { 543 {
492 lock (m_UrlMap) 544 UrlData url=null;
545
546 lock (m_RequestMap)
493 { 547 {
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)) 548 if (!m_RequestMap.ContainsKey(requestID))
500 { 549 {
501 return true; 550 return false;
502 } 551 }
503 552 url = m_RequestMap[requestID];
504 UrlData urlData = m_RequestMap[requestID]; 553 }
505 554 lock (url.requests)
506 if (!urlData.requests.ContainsKey(requestID)) 555 {
556 if (!url.requests.ContainsKey(requestID))
507 { 557 {
508 return true; 558 return false;
509 } 559 }
510 560 else
511 // Trigger return of timeout response.
512 if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000)
513 { 561 {
514 return true; 562 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
563 {
564 return true;
565 }
566 if (url.requests[requestID].requestDone)
567 return true;
568 else
569 return false;
515 } 570 }
516
517 return urlData.requests[requestID].requestDone;
518 } 571 }
519 } 572 }
520 573 protected Hashtable GetEvents(UUID requestID, UUID sessionID)
521 private Hashtable GetEvents(UUID requestID, UUID sessionID)
522 { 574 {
523 Hashtable response; 575 UrlData url = null;
576 RequestData requestData = null;
524 577
525 lock (m_UrlMap) 578 lock (m_RequestMap)
526 { 579 {
527 UrlData url = null;
528 RequestData requestData = null;
529
530 if (!m_RequestMap.ContainsKey(requestID)) 580 if (!m_RequestMap.ContainsKey(requestID))
531 return NoEvents(requestID, sessionID); 581 return NoEvents(requestID,sessionID);
532
533 url = m_RequestMap[requestID]; 582 url = m_RequestMap[requestID];
583 }
584 lock (url.requests)
585 {
534 requestData = url.requests[requestID]; 586 requestData = url.requests[requestID];
587 }
535 588
536 if (!requestData.requestDone) 589 if (!requestData.requestDone)
537 return NoEvents(requestID, sessionID); 590 return NoEvents(requestID,sessionID);
538
539 response = new Hashtable();
540 591
541 if (System.Environment.TickCount - requestData.startTime > 25000) 592 Hashtable response = new Hashtable();
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 593
551 //put response 594 if (System.Environment.TickCount - requestData.startTime > 25000)
552 response["int_response_code"] = requestData.responseCode; 595 {
553 response["str_response_string"] = requestData.responseBody; 596 response["int_response_code"] = 500;
554 response["content_type"] = requestData.responseType; 597 response["str_response_string"] = "Script timeout";
555 // response["content_type"] = "text/plain"; 598 response["content_type"] = "text/plain";
556 response["keepalive"] = false; 599 response["keepalive"] = false;
557 response["reusecontext"] = false; 600 response["reusecontext"] = false;
558 601 return response;
559 //remove from map 602 }
603 //put response
604 response["int_response_code"] = requestData.responseCode;
605 response["str_response_string"] = requestData.responseBody;
606 response["content_type"] = requestData.responseType;
607 response["keepalive"] = false;
608 response["reusecontext"] = false;
609
610 if (url.allowXss)
611 response["access_control_allow_origin"] = "*";
612
613 //remove from map
614 lock (url.requests)
615 {
560 url.requests.Remove(requestID); 616 url.requests.Remove(requestID);
617 }
618 lock (m_RequestMap)
619 {
561 m_RequestMap.Remove(requestID); 620 m_RequestMap.Remove(requestID);
562 } 621 }
563 622
@@ -566,44 +625,49 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
566 625
567 public void HttpRequestHandler(UUID requestID, Hashtable request) 626 public void HttpRequestHandler(UUID requestID, Hashtable request)
568 { 627 {
569 string uri = request["uri"].ToString(); 628 lock (request)
570 bool is_ssl = uri.Contains("lslhttps");
571
572 try
573 { 629 {
574 Hashtable headers = (Hashtable)request["headers"]; 630 string uri = request["uri"].ToString();
631 bool is_ssl = uri.Contains("lslhttps");
575 632
576// string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; 633 try
634 {
635 Hashtable headers = (Hashtable)request["headers"];
577 636
578 int pos1 = uri.IndexOf("/");// /lslhttp 637// 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 638
587 pathInfo = uri.Substring(pos3); 639 int pos1 = uri.IndexOf("/");// /lslhttp
640 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
641 int pos3 = uri.IndexOf("/", pos2 + 1); // /lslhttp/urlcode
588 642
589 UrlData urlData = null; 643 string uri_tmp = uri.Substring(0, pos3 + 1);
644 //HTTP server code doesn't provide us with QueryStrings
645 string pathInfo;
646 string queryString;
647 queryString = "";
590 648
591 lock (m_UrlMap) 649 pathInfo = uri.Substring(pos3);
592 {
593 string url;
594 650
595 if (is_ssl) 651 UrlData url = null;
596 url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; 652 string urlkey;
653 if (!is_ssl)
654 urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
655 //m_UrlMap[];
597 else 656 else
598 url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; 657 urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
599 658
600 // Avoid a race - the request URL may have been released via llRequestUrl() whilst this 659 if (m_UrlMap.ContainsKey(urlkey))
601 // request was being processed. 660 {
602 if (!m_UrlMap.TryGetValue(url, out urlData)) 661 url = m_UrlMap[urlkey];
662 }
663 else
664 {
665 //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString());
603 return; 666 return;
667 }
604 668
605 //for llGetHttpHeader support we need to store original URI here 669 //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 670 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
607 //as per http://wiki.secondlife.com/wiki/LlGetHTTPHeader 671 //as per http://wiki.secondlife.com/wiki/LlGetHTTPHeader
608 672
609 RequestData requestData = new RequestData(); 673 RequestData requestData = new RequestData();
@@ -611,6 +675,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
611 requestData.requestDone = false; 675 requestData.requestDone = false;
612 requestData.startTime = System.Environment.TickCount; 676 requestData.startTime = System.Environment.TickCount;
613 requestData.uri = uri; 677 requestData.uri = uri;
678 requestData.hostID = url.hostID;
679 requestData.scene = url.scene;
614 if (requestData.headers == null) 680 if (requestData.headers == null)
615 requestData.headers = new Dictionary<string, string>(); 681 requestData.headers = new Dictionary<string, string>();
616 682
@@ -619,8 +685,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
619 string key = (string)header.Key; 685 string key = (string)header.Key;
620 string value = (string)header.Value; 686 string value = (string)header.Value;
621 requestData.headers.Add(key, value); 687 requestData.headers.Add(key, value);
688 if (key == "cookie")
689 {
690 string[] parts = value.Split(new char[] {'='});
691 if (parts[0] == "agni_sl_session_id" && parts.Length > 1)
692 {
693 string cookie = Uri.UnescapeDataString(parts[1]);
694 string[] crumbs = cookie.Split(new char[] {':'});
695 UUID owner;
696 if (crumbs.Length == 2 && UUID.TryParse(crumbs[0], out owner))
697 {
698 if (crumbs[1].Length == 32)
699 {
700 Scene scene = requestData.scene;
701 if (scene != null)
702 {
703 SceneObjectPart host = scene.GetSceneObjectPart(requestData.hostID);
704 if (host != null)
705 {
706 if (host.OwnerID == owner)
707 requestData.allowResponseType = true;
708 }
709 }
710 }
711 }
712 }
713 }
622 } 714 }
623
624 foreach (DictionaryEntry de in request) 715 foreach (DictionaryEntry de in request)
625 { 716 {
626 if (de.Key.ToString() == "querystringkeys") 717 if (de.Key.ToString() == "querystringkeys")
@@ -631,13 +722,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
631 if (request.ContainsKey(key)) 722 if (request.ContainsKey(key))
632 { 723 {
633 string val = (String)request[key]; 724 string val = (String)request[key];
634 queryString = queryString + key + "=" + val + "&"; 725 if (key != "")
726 {
727 queryString = queryString + key + "=" + val + "&";
728 }
729 else
730 {
731 queryString = queryString + val + "&";
732 }
635 } 733 }
636 } 734 }
637
638 if (queryString.Length > 1) 735 if (queryString.Length > 1)
639 queryString = queryString.Substring(0, queryString.Length - 1); 736 queryString = queryString.Substring(0, queryString.Length - 1);
737
640 } 738 }
739
641 } 740 }
642 741
643 //if this machine is behind DNAT/port forwarding, currently this is being 742 //if this machine is behind DNAT/port forwarding, currently this is being
@@ -645,27 +744,38 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
645 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; 744 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"];
646 requestData.headers["x-path-info"] = pathInfo; 745 requestData.headers["x-path-info"] = pathInfo;
647 requestData.headers["x-query-string"] = queryString; 746 requestData.headers["x-query-string"] = queryString;
648 requestData.headers["x-script-url"] = urlData.url; 747 requestData.headers["x-script-url"] = url.url;
649 748
650 urlData.requests.Add(requestID, requestData); 749 //requestData.ev = new ManualResetEvent(false);
651 m_RequestMap.Add(requestID, urlData); 750 lock (url.requests)
652 } 751 {
752 url.requests.Add(requestID, requestData);
753 }
754 lock (m_RequestMap)
755 {
756 //add to request map
757 m_RequestMap.Add(requestID, url);
758 }
653 759
654 urlData.engine.PostScriptEvent( 760 url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
655 urlData.itemID, 761
656 "http_request", 762 //send initial response?
657 new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); 763// Hashtable response = new Hashtable();
658 } 764
659 catch (Exception we) 765 return;
660 { 766
661 //Hashtable response = new Hashtable(); 767 }
662 m_log.Warn("[HttpRequestHandler]: http-in request failed"); 768 catch (Exception we)
663 m_log.Warn(we.Message); 769 {
664 m_log.Warn(we.StackTrace); 770 //Hashtable response = new Hashtable();
771 m_log.Warn("[HttpRequestHandler]: http-in request failed");
772 m_log.Warn(we.Message);
773 m_log.Warn(we.StackTrace);
774 }
665 } 775 }
666 } 776 }
667 777
668 private void OnScriptReset(uint localID, UUID itemID) 778 protected void OnScriptReset(uint localID, UUID itemID)
669 { 779 {
670 ScriptRemoved(itemID); 780 ScriptRemoved(itemID);
671 } 781 }
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index d45962f..673a453 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
98 return false; 98 return false;
99 } 99 }
100 100
101 public void GetDrawStringSize(string text, string fontName, int fontSize, 101 public void GetDrawStringSize(string text, string fontName, int fontSize,
102 out double xSize, out double ySize) 102 out double xSize, out double ySize)
103 { 103 {
104 xSize = 0; 104 xSize = 0;
@@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
124 { 124 {
125 if (m_scene == null) 125 if (m_scene == null)
126 m_scene = scene; 126 m_scene = scene;
127 127
128 } 128 }
129 129
130 public void RemoveRegion(Scene scene) 130 public void RemoveRegion(Scene scene)
@@ -166,15 +166,15 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
166 166
167 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 167 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
168 request.AllowAutoRedirect = false; 168 request.AllowAutoRedirect = false;
169 169
170 if (!string.IsNullOrEmpty(m_proxyurl)) 170 if (!string.IsNullOrEmpty(m_proxyurl))
171 { 171 {
172 if (!string.IsNullOrEmpty(m_proxyexcepts)) 172 if (!string.IsNullOrEmpty(m_proxyexcepts))
173 { 173 {
174 string[] elist = m_proxyexcepts.Split(';'); 174 string[] elist = m_proxyexcepts.Split(';');
175 request.Proxy = new WebProxy(m_proxyurl, true, elist); 175 request.Proxy = new WebProxy(m_proxyurl, true, elist);
176 } 176 }
177 else 177 else
178 { 178 {
179 request.Proxy = new WebProxy(m_proxyurl, true); 179 request.Proxy = new WebProxy(m_proxyurl, true);
180 } 180 }
@@ -253,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
253 { 253 {
254 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 254 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
255 } 255 }
256 } 256 }
257 catch (Exception) 257 catch (Exception)
258 { 258 {
259 m_log.Error("[LOADIMAGEURLMODULE]: OpenJpeg Conversion Failed. Empty byte data returned!"); 259 m_log.Error("[LOADIMAGEURLMODULE]: OpenJpeg Conversion Failed. Empty byte data returned!");
@@ -268,33 +268,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
268 catch (WebException) 268 catch (WebException)
269 { 269 {
270 } 270 }
271 catch (Exception e)
272 {
273 m_log.ErrorFormat("[LOADIMAGEURLMODULE]: unexpected exception {0}", e.Message);
274 }
271 finally 275 finally
272 { 276 {
273 if (stream != null) 277 if (stream != null)
274 stream.Close(); 278 stream.Close();
275 279
276 if (response != null) 280 if (response != null)
277 response.Close();
278
279 if (
280 response.StatusCode == HttpStatusCode.MovedPermanently
281 || response.StatusCode == HttpStatusCode.Found
282 || response.StatusCode == HttpStatusCode.SeeOther
283 || response.StatusCode == HttpStatusCode.TemporaryRedirect)
284 { 281 {
285 string redirectedUrl = response.Headers["Location"]; 282 if (response.StatusCode == HttpStatusCode.MovedPermanently
283 || response.StatusCode == HttpStatusCode.Found
284 || response.StatusCode == HttpStatusCode.SeeOther
285 || response.StatusCode == HttpStatusCode.TemporaryRedirect)
286 {
287 string redirectedUrl = response.Headers["Location"];
286 288
287 MakeHttpRequest(redirectedUrl, state.RequestID); 289 MakeHttpRequest(redirectedUrl, state.RequestID);
288 } 290 }
289 else 291 else
290 { 292 {
291 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}", 293 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
292 imageJ2000.Length, state.RequestID); 294 imageJ2000.Length, state.RequestID);
293 295
294 m_textureManager.ReturnData( 296 m_textureManager.ReturnData(
295 state.RequestID, 297 state.RequestID,
296 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( 298 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
297 request.RequestUri, null, imageJ2000, newSize, false)); 299 request.RequestUri, null, imageJ2000, newSize, false));
300 }
301 response.Close();
298 } 302 }
299 } 303 }
300 } 304 }
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index 6da2222..9c3f08e 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -89,7 +89,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
89 public void RegionLoaded(Scene scene) 89 public void RegionLoaded(Scene scene)
90 { 90 {
91 m_scriptModule = scene.RequestModuleInterface<IScriptModule>(); 91 m_scriptModule = scene.RequestModuleInterface<IScriptModule>();
92 92
93 if (m_scriptModule != null) 93 if (m_scriptModule != null)
94 m_log.Info("[MODULE COMMANDS]: Script engine found, module active"); 94 m_log.Info("[MODULE COMMANDS]: Script engine found, module active");
95 } 95 }
@@ -237,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
237 } 237 }
238 } 238 }
239 } 239 }
240 240
241 public Delegate[] GetScriptInvocationList() 241 public Delegate[] GetScriptInvocationList()
242 { 242 {
243 List<Delegate> ret = new List<Delegate>(); 243 List<Delegate> ret = new List<Delegate>();
@@ -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 }
@@ -359,14 +361,14 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
359 public object LookupModConstant(string cname) 361 public object LookupModConstant(string cname)
360 { 362 {
361 // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); 363 // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname);
362 364
363 lock (m_constants) 365 lock (m_constants)
364 { 366 {
365 object value = null; 367 object value = null;
366 if (m_constants.TryGetValue(cname,out value)) 368 if (m_constants.TryGetValue(cname,out value))
367 return value; 369 return value;
368 } 370 }
369 371
370 return null; 372 return null;
371 } 373 }
372 374
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index ed255bf..325f7f9 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -77,8 +77,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
77 so.UUID, 77 so.UUID,
78 m_vrm.GetContentType(), 78 m_vrm.GetContentType(),
79 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 79 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
80 "", 80 "");
81 0);
82 81
83 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 82 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
84 } 83 }
@@ -98,8 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
98 so.UUID, 97 so.UUID,
99 m_vrm.GetContentType(), 98 m_vrm.GetContentType(),
100 dtText, 99 dtText,
101 "", 100 "");
102 0);
103 101
104 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 102 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
105 103
@@ -108,8 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
108 so.UUID, 106 so.UUID,
109 m_vrm.GetContentType(), 107 m_vrm.GetContentType(),
110 dtText, 108 dtText,
111 "", 109 "");
112 0);
113 110
114 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 111 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
115 } 112 }
@@ -129,8 +126,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
129 so.UUID, 126 so.UUID,
130 m_vrm.GetContentType(), 127 m_vrm.GetContentType(),
131 dtText, 128 dtText,
132 "", 129 "");
133 0);
134 130
135 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 131 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
136 132
@@ -139,8 +135,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
139 so.UUID, 135 so.UUID,
140 m_vrm.GetContentType(), 136 m_vrm.GetContentType(),
141 dtText, 137 dtText,
142 "alpha:250", 138 "alpha:250");
143 0);
144 139
145 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 140 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
146 } 141 }
@@ -161,8 +156,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
161 so.UUID, 156 so.UUID,
162 m_vrm.GetContentType(), 157 m_vrm.GetContentType(),
163 dtText, 158 dtText,
164 "", 159 "");
165 0);
166 160
167 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 161 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
168 162
@@ -171,8 +165,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
171 so.UUID, 165 so.UUID,
172 m_vrm.GetContentType(), 166 m_vrm.GetContentType(),
173 dtText, 167 dtText,
174 "", 168 "");
175 0);
176 169
177 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 170 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
178 } 171 }
@@ -191,8 +184,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
191 so.UUID, 184 so.UUID,
192 m_vrm.GetContentType(), 185 m_vrm.GetContentType(),
193 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 186 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
194 "", 187 "");
195 0);
196 188
197 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 189 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
198 } 190 }
@@ -213,8 +205,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
213 so.UUID, 205 so.UUID,
214 m_vrm.GetContentType(), 206 m_vrm.GetContentType(),
215 dtText, 207 dtText,
216 "", 208 "");
217 0);
218 209
219 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 210 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
220 211
@@ -223,8 +214,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
223 so.UUID, 214 so.UUID,
224 m_vrm.GetContentType(), 215 m_vrm.GetContentType(),
225 dtText, 216 dtText,
226 "", 217 "");
227 0);
228 218
229 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 219 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
230 } 220 }
@@ -253,8 +243,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
253 so.UUID, 243 so.UUID,
254 m_vrm.GetContentType(), 244 m_vrm.GetContentType(),
255 dtText, 245 dtText,
256 "1024", 246 "1024");
257 0);
258 247
259 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 248 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
260 249
@@ -263,8 +252,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
263 so.UUID, 252 so.UUID,
264 m_vrm.GetContentType(), 253 m_vrm.GetContentType(),
265 dtText, 254 dtText,
266 "1024", 255 "1024");
267 0);
268 256
269 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 257 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
270 } 258 }
@@ -284,8 +272,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
284 so.UUID, 272 so.UUID,
285 m_vrm.GetContentType(), 273 m_vrm.GetContentType(),
286 dtText, 274 dtText,
287 "", 275 "");
288 0);
289 276
290 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 277 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
291 278
@@ -294,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
294 so.UUID, 281 so.UUID,
295 m_vrm.GetContentType(), 282 m_vrm.GetContentType(),
296 dtText, 283 dtText,
297 "alpha:250", 284 "alpha:250");
298 0);
299 285
300 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 286 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
301 } 287 }
@@ -316,8 +302,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
316 so.UUID, 302 so.UUID,
317 m_vrm.GetContentType(), 303 m_vrm.GetContentType(),
318 dtText, 304 dtText,
319 "", 305 "");
320 0);
321 306
322 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 307 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
323 308
@@ -326,8 +311,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
326 so.UUID, 311 so.UUID,
327 m_vrm.GetContentType(), 312 m_vrm.GetContentType(),
328 dtText, 313 dtText,
329 "", 314 "");
330 0);
331 315
332 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 316 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
333 } 317 }
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 4cecd85..8a26ab7 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
117 return true; 117 return true;
118 } 118 }
119 119
120 public void GetDrawStringSize(string text, string fontName, int fontSize, 120 public void GetDrawStringSize(string text, string fontName, int fontSize,
121 out double xSize, out double ySize) 121 out double xSize, out double ySize)
122 { 122 {
123 lock (this) 123 lock (this)
@@ -209,32 +209,32 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
209 int alpha = 255; // 0 is transparent 209 int alpha = 255; // 0 is transparent
210 Color bgColor = Color.White; // Default background color 210 Color bgColor = Color.White; // Default background color
211 char altDataDelim = ';'; 211 char altDataDelim = ';';
212 212
213 char[] paramDelimiter = { ',' }; 213 char[] paramDelimiter = { ',' };
214 char[] nvpDelimiter = { ':' }; 214 char[] nvpDelimiter = { ':' };
215 215
216 extraParams = extraParams.Trim(); 216 extraParams = extraParams.Trim();
217 extraParams = extraParams.ToLower(); 217 extraParams = extraParams.ToLower();
218 218
219 string[] nvps = extraParams.Split(paramDelimiter); 219 string[] nvps = extraParams.Split(paramDelimiter);
220 220
221 int temp = -1; 221 int temp = -1;
222 foreach (string pair in nvps) 222 foreach (string pair in nvps)
223 { 223 {
224 string[] nvp = pair.Split(nvpDelimiter); 224 string[] nvp = pair.Split(nvpDelimiter);
225 string name = ""; 225 string name = "";
226 string value = ""; 226 string value = "";
227 227
228 if (nvp[0] != null) 228 if (nvp[0] != null)
229 { 229 {
230 name = nvp[0].Trim(); 230 name = nvp[0].Trim();
231 } 231 }
232 232
233 if (nvp.Length == 2) 233 if (nvp.Length == 2)
234 { 234 {
235 value = nvp[1].Trim(); 235 value = nvp[1].Trim();
236 } 236 }
237 237
238 switch (name) 238 switch (name)
239 { 239 {
240 case "width": 240 case "width":
@@ -301,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
301 if (Int32.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) 301 if (Int32.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
302 { 302 {
303 bgColor = Color.FromArgb(hex); 303 bgColor = Color.FromArgb(hex);
304 } 304 }
305 else 305 else
306 { 306 {
307 bgColor = Color.FromName(value); 307 bgColor = Color.FromName(value);
@@ -321,7 +321,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
321 } 321 }
322 else 322 else
323 { 323 {
324 // this function used to accept an int on its own that represented both 324 // this function used to accept an int on its own that represented both
325 // width and height, this is to maintain backwards compat, could be removed 325 // width and height, this is to maintain backwards compat, could be removed
326 // but would break existing scripts 326 // but would break existing scripts
327 temp = parseIntParam(name); 327 temp = parseIntParam(name);
@@ -329,10 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
329 { 329 {
330 if (temp > 1024) 330 if (temp > 1024)
331 temp = 1024; 331 temp = 1024;
332 332
333 if (temp < 128) 333 if (temp < 128)
334 temp = 128; 334 temp = 128;
335 335
336 width = temp; 336 width = temp;
337 height = temp; 337 height = temp;
338 } 338 }
@@ -355,36 +355,28 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
355 lock (this) 355 lock (this)
356 { 356 {
357 if (alpha == 256) 357 if (alpha == 256)
358 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
359 else
360 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
361
362 graph = Graphics.FromImage(bitmap);
363
364 // this is really just to save people filling the
365 // background color in their scripts, only do when fully opaque
366 if (alpha >= 255)
367 { 358 {
359 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
360 graph = Graphics.FromImage(bitmap);
368 using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) 361 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
369 { 362 {
370 graph.FillRectangle(bgFillBrush, 0, 0, width, height); 363 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
371 } 364 }
372 } 365 }
373 366 else
374 for (int w = 0; w < bitmap.Width; w++)
375 { 367 {
376 if (alpha <= 255) 368 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
369 graph = Graphics.FromImage(bitmap);
370 Color newbg = Color.FromArgb(alpha,bgColor);
371 using (SolidBrush bgFillBrush = new SolidBrush(newbg))
377 { 372 {
378 for (int h = 0; h < bitmap.Height; h++) 373 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
379 {
380 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
381 }
382 } 374 }
383 } 375 }
384 376
385 GDIDraw(data, graph, altDataDelim, out reuseable); 377 GDIDraw(data, graph, altDataDelim, out reuseable);
386 } 378 }
387 379
388 byte[] imageJ2000 = new byte[0]; 380 byte[] imageJ2000 = new byte[0];
389 381
390 // This code exists for testing purposes, please do not remove. 382 // This code exists for testing purposes, please do not remove.
@@ -394,7 +386,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
394// imageJ2000 = s_asset2Data; 386// imageJ2000 = s_asset2Data;
395// 387//
396// s_flipper = !s_flipper; 388// s_flipper = !s_flipper;
397 389
398 try 390 try
399 { 391 {
400 imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); 392 imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true);
@@ -420,13 +412,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
420 { 412 {
421 if (graph != null) 413 if (graph != null)
422 graph.Dispose(); 414 graph.Dispose();
423 415
424 if (bitmap != null) 416 if (bitmap != null)
425 bitmap.Dispose(); 417 bitmap.Dispose();
426 } 418 }
427 } 419 }
428 } 420 }
429 421
430 private int parseIntParam(string strInt) 422 private int parseIntParam(string strInt)
431 { 423 {
432 int parsed; 424 int parsed;
@@ -440,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
440 // m_log.Debug("Problem with Draw. Please verify parameters." + e.ToString()); 432 // m_log.Debug("Problem with Draw. Please verify parameters." + e.ToString());
441 parsed = -1; 433 parsed = -1;
442 } 434 }
443 435
444 return parsed; 436 return parsed;
445 } 437 }
446 438
@@ -519,8 +511,32 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
519 511
520// m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine); 512// m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine);
521 513
514 if (nextLine.StartsWith("ResetTransf"))
515 {
516 graph.ResetTransform();
517 }
518 else if (nextLine.StartsWith("TransTransf"))
519 {
520 float x = 0;
521 float y = 0;
522 GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y);
523 graph.TranslateTransform(x, y);
524 }
525 else if (nextLine.StartsWith("ScaleTransf"))
526 {
527 float x = 0;
528 float y = 0;
529 GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y);
530 graph.ScaleTransform(x, y);
531 }
532 else if (nextLine.StartsWith("RotTransf"))
533 {
534 float x = 0;
535 GetParams(partsDelimiter, ref nextLine, 9, ref x);
536 graph.RotateTransform(x);
537 }
522 //replace with switch, or even better, do some proper parsing 538 //replace with switch, or even better, do some proper parsing
523 if (nextLine.StartsWith("MoveTo")) 539 else if (nextLine.StartsWith("MoveTo"))
524 { 540 {
525 float x = 0; 541 float x = 0;
526 float y = 0; 542 float y = 0;
@@ -572,7 +588,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
572 graph.DrawString("not an image. Please check URL.", errorFont, 588 graph.DrawString("not an image. Please check URL.", errorFont,
573 myBrush, new Point(startPoint.X, 12 + startPoint.Y)); 589 myBrush, new Point(startPoint.X, 12 + startPoint.Y));
574 } 590 }
575 591
576 graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); 592 graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
577 } 593 }
578 } 594 }
@@ -625,6 +641,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
625 startPoint.X += endPoint.X; 641 startPoint.X += endPoint.X;
626 startPoint.Y += endPoint.Y; 642 startPoint.Y += endPoint.Y;
627 } 643 }
644 else if (nextLine.StartsWith("FillEllipse"))
645 {
646 float x = 0;
647 float y = 0;
648 GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y);
649 endPoint.X = (int)x;
650 endPoint.Y = (int)y;
651 graph.FillEllipse(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
652 startPoint.X += endPoint.X;
653 startPoint.Y += endPoint.Y;
654 }
628 else if (nextLine.StartsWith("FontSize")) 655 else if (nextLine.StartsWith("FontSize"))
629 { 656 {
630 nextLine = nextLine.Remove(0, 8); 657 nextLine = nextLine.Remove(0, 8);
@@ -638,11 +665,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
638 { 665 {
639 nextLine = nextLine.Remove(0, 8); 666 nextLine = nextLine.Remove(0, 8);
640 nextLine = nextLine.Trim(); 667 nextLine = nextLine.Trim();
641 668
642 string[] fprops = nextLine.Split(partsDelimiter); 669 string[] fprops = nextLine.Split(partsDelimiter);
643 foreach (string prop in fprops) 670 foreach (string prop in fprops)
644 { 671 {
645 672
646 switch (prop) 673 switch (prop)
647 { 674 {
648 case "B": 675 case "B":
@@ -717,7 +744,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
717 else if (cap[0].ToLower() != "both") 744 else if (cap[0].ToLower() != "both")
718 return; 745 return;
719 string type = cap[1].ToLower(); 746 string type = cap[1].ToLower();
720 747
721 if (end) 748 if (end)
722 { 749 {
723 switch (type) 750 switch (type)
@@ -760,7 +787,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
760 nextLine = nextLine.Remove(0, 9); 787 nextLine = nextLine.Remove(0, 9);
761 nextLine = nextLine.Trim(); 788 nextLine = nextLine.Trim();
762 int hex = 0; 789 int hex = 0;
763 790
764 Color newColor; 791 Color newColor;
765 if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) 792 if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex))
766 { 793 {
@@ -790,6 +817,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
790 } 817 }
791 } 818 }
792 819
820 private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x)
821 {
822 line = line.Remove(0, startLength);
823 string[] parts = line.Split(partsDelimiter);
824 if (parts.Length > 0)
825 {
826 string xVal = parts[0].Trim();
827 x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
828 }
829 }
830
793 private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) 831 private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y)
794 { 832 {
795 line = line.Remove(0, startLength); 833 line = line.Remove(0, startLength);
@@ -861,4 +899,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
861 return null; 899 return null;
862 } 900 }
863 } 901 }
864} \ No newline at end of file 902}
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index 3484387..a5203ea 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;
@@ -111,7 +113,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
111 // wrap this in a try block so that defaults will work if 113 // wrap this in a try block so that defaults will work if
112 // the config file doesn't specify otherwise. 114 // the config file doesn't specify otherwise.
113 int maxlisteners = 1000; 115 int maxlisteners = 1000;
114 int maxhandles = 64; 116 int maxhandles = 65;
115 try 117 try
116 { 118 {
117 m_whisperdistance = config.Configs["Chat"].GetInt( 119 m_whisperdistance = config.Configs["Chat"].GetInt(
@@ -128,8 +130,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
128 catch (Exception) 130 catch (Exception)
129 { 131 {
130 } 132 }
131 if (maxlisteners < 1) maxlisteners = int.MaxValue; 133
132 if (maxhandles < 1) maxhandles = int.MaxValue; 134 if (maxlisteners < 1)
135 maxlisteners = int.MaxValue;
136 if (maxhandles < 1)
137 maxhandles = int.MaxValue;
138
139 if (maxlisteners < maxhandles)
140 maxlisteners = maxhandles;
141
133 m_listenerManager = new ListenerManager(maxlisteners, maxhandles); 142 m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
134 m_pendingQ = new Queue(); 143 m_pendingQ = new Queue();
135 m_pending = Queue.Synchronized(m_pendingQ); 144 m_pending = Queue.Synchronized(m_pendingQ);
@@ -309,6 +318,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
309 // Determine which listen event filters match the given set of arguments, this results 318 // Determine which listen event filters match the given set of arguments, this results
310 // in a limited set of listeners, each belonging a host. If the host is in range, add them 319 // in a limited set of listeners, each belonging a host. If the host is in range, add them
311 // to the pending queue. 320 // to the pending queue.
321
312 foreach (ListenerInfo li 322 foreach (ListenerInfo li
313 in m_listenerManager.GetListeners(UUID.Zero, channel, 323 in m_listenerManager.GetListeners(UUID.Zero, channel,
314 name, id, msg)) 324 name, id, msg))
@@ -366,79 +376,82 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
366 /// <param name='msg'> 376 /// <param name='msg'>
367 /// Message. 377 /// Message.
368 /// </param> 378 /// </param>
369 public void DeliverMessageTo(UUID target, int channel, Vector3 pos, 379 public void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg)
370 string name, UUID id, string msg)
371 { 380 {
372 // Is id an avatar? 381 if (channel == DEBUG_CHANNEL)
373 ScenePresence sp = m_scene.GetScenePresence(target); 382 return;
374 383
384 if(target == UUID.Zero)
385 return;
386
387 // Is target an avatar?
388 ScenePresence sp = m_scene.GetScenePresence(target);
375 if (sp != null) 389 if (sp != null)
376 { 390 {
377 // ignore if a child agent this is restricted to inside one 391 // Send message to avatar
378 // region 392 if (channel == 0)
379 if (sp.IsChildAgent) 393 {
394 // Channel 0 goes to viewer ONLY
395 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
380 return; 396 return;
397 }
381 398
382 // Channel zero only goes to the avatar 399 // for now messages to prims don't cross regions
383 // non zero channel messages only go to the attachments of the avatar. 400 if(sp.IsChildAgent)
384 if (channel != 0) 401 return;
385 {
386 List<SceneObjectGroup> attachments = sp.GetAttachments();
387 if (attachments.Count == 0)
388 return;
389 402
390 // Get uuid of attachments 403 List<SceneObjectGroup> attachments = sp.GetAttachments();
391 List<UUID> targets = new List<UUID>(); 404
392 foreach (SceneObjectGroup sog in attachments) 405 if (attachments.Count == 0)
393 { 406 return;
394 if (!sog.IsDeleted)
395 targets.Add(sog.UUID);
396 }
397 407
398 // Need to check each attachment 408 // Get uuid of attachments
399 foreach (ListenerInfo li 409 List<UUID> targets = new List<UUID>();
400 in m_listenerManager.GetListeners(UUID.Zero, 410 foreach (SceneObjectGroup sog in attachments)
401 channel, name, id, msg)) 411 {
412 if (!sog.IsDeleted)
402 { 413 {
403 if (li.GetHostID().Equals(id)) 414 SceneObjectPart[] parts = sog.Parts;
404 continue; 415 foreach(SceneObjectPart p in parts)
416 targets.Add(p.UUID);
417 }
418 }
405 419
406 if (m_scene.GetSceneObjectPart( 420 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
407 li.GetHostID()) == null) 421 {
408 { 422 UUID liHostID = li.GetHostID();
409 continue; 423 if (liHostID.Equals(id))
410 } 424 continue;
425 if (m_scene.GetSceneObjectPart(liHostID) == null)
426 continue;
411 427
412 if (targets.Contains(li.GetHostID())) 428 if (targets.Contains(liHostID))
413 QueueMessage(new ListenerInfo(li, name, id, msg)); 429 QueueMessage(new ListenerInfo(li, name, id, msg));
414 }
415 } 430 }
416 431
417 return; 432 return;
418 } 433 }
419 434
420 // No avatar found so look for an object 435 SceneObjectPart part = m_scene.GetSceneObjectPart(target);
421 foreach (ListenerInfo li 436 if (part == null) // Not even an object
422 in m_listenerManager.GetListeners(UUID.Zero, channel, 437 return; // No error
423 name, id, msg)) 438
439 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
424 { 440 {
441 UUID liHostID = li.GetHostID();
425 // Dont process if this message is from yourself! 442 // Dont process if this message is from yourself!
426 if (li.GetHostID().Equals(id)) 443 if (liHostID.Equals(id))
427 continue; 444 continue;
428 445
429 SceneObjectPart sPart = m_scene.GetSceneObjectPart( 446 if (m_scene.GetSceneObjectPart(liHostID) == null)
430 li.GetHostID());
431 if (sPart == null)
432 continue; 447 continue;
433 448
434 if (li.GetHostID().Equals(target)) 449 if (liHostID.Equals(target))
435 { 450 {
436 QueueMessage(new ListenerInfo(li, name, id, msg)); 451 QueueMessage(new ListenerInfo(li, name, id, msg));
437 break; 452 break;
438 } 453 }
439 } 454 }
440
441 return;
442 } 455 }
443 456
444 protected void QueueMessage(ListenerInfo li) 457 protected void QueueMessage(ListenerInfo li)
@@ -557,9 +570,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
557 return coll[0].GetHandle(); 570 return coll[0].GetHandle();
558 } 571 }
559 572
560 if (m_curlisteners < m_maxlisteners) 573 lock (m_listeners)
561 { 574 {
562 lock (m_listeners) 575 if (m_curlisteners < m_maxlisteners)
563 { 576 {
564 int newHandle = GetNewHandle(itemID); 577 int newHandle = GetNewHandle(itemID);
565 578
@@ -599,11 +612,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
599 li.GetHandle().Equals(handle)) 612 li.GetHandle().Equals(handle))
600 { 613 {
601 lis.Value.Remove(li); 614 lis.Value.Remove(li);
615 m_curlisteners--;
602 if (lis.Value.Count == 0) 616 if (lis.Value.Count == 0)
603 { 617 m_listeners.Remove(lis.Key); // bailing of loop so this does not smoke
604 m_listeners.Remove(lis.Key);
605 m_curlisteners--;
606 }
607 // there should be only one, so we bail out early 618 // there should be only one, so we bail out early
608 return; 619 return;
609 } 620 }
@@ -712,6 +723,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
712 } 723 }
713 } 724 }
714 725
726 if(handles.Count >= m_maxhandles)
727 return -1;
728
715 // Note: 0 is NOT a valid handle for llListen() to return 729 // Note: 0 is NOT a valid handle for llListen() to return
716 for (int i = 1; i <= m_maxhandles; i++) 730 for (int i = 1; i <= m_maxhandles; i++)
717 { 731 {
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index 87f4277..6028eef 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -621,7 +621,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
621 private Thread httpThread; 621 private Thread httpThread;
622 public int Idata; 622 public int Idata;
623 private UUID _itemID; 623 private UUID _itemID;
624 public UUID ItemID 624 public UUID ItemID
625 { 625 {
626 get { return _itemID; } 626 get { return _itemID; }
627 set { _itemID = value; } 627 set { _itemID = value; }
@@ -633,7 +633,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
633 set { _localID = value; } 633 set { _localID = value; }
634 } 634 }
635 private UUID _reqID; 635 private UUID _reqID;
636 public UUID ReqID 636 public UUID ReqID
637 { 637 {
638 get { return _reqID; } 638 get { return _reqID; }
639 set { _reqID = value; } 639 set { _reqID = value; }
@@ -658,7 +658,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
658 public void Process() 658 public void Process()
659 { 659 {
660 _finished = false; 660 _finished = false;
661 httpThread = WorkManager.StartThread(SendRequest, "HttpRequestThread", ThreadPriority.BelowNormal, true, false); 661 httpThread = WorkManager.StartThread(SendRequest, "XMLRPCreqThread", ThreadPriority.BelowNormal, true, false, null, int.MaxValue);
662 } 662 }
663 663
664 /* 664 /*
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
index 7b4668a..2c882e6 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private static bool m_Enabled = false; 47 private static bool m_Enabled = false;
48 48
49 private IConfigSource m_Config; 49 private IConfigSource m_Config;
50 bool m_Registered = false; 50 bool m_Registered = false;
51 51
@@ -74,7 +74,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset
74 { 74 {
75 } 75 }
76 76
77 public Type ReplaceableInterface 77 public Type ReplaceableInterface
78 { 78 {
79 get { return null; } 79 get { return null; }
80 } 80 }
@@ -95,7 +95,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset
95 95
96 m_log.Info("[HGAssetService]: Starting..."); 96 m_log.Info("[HGAssetService]: Starting...");
97 97
98 98
99 Object[] args = new Object[] { m_Config, MainServer.Instance, "HGAssetService" }; 99 Object[] args = new Object[] { m_Config, MainServer.Instance, "HGAssetService" };
100 100
101 ServerUtils.LoadPlugin<IServiceConnector>("OpenSim.Server.Handlers.dll:AssetServiceConnector", args); 101 ServerUtils.LoadPlugin<IServiceConnector>("OpenSim.Server.Handlers.dll:AssetServiceConnector", args);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
index 2cdffe6..a8c4e3c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private static bool m_Enabled = false; 49 private static bool m_Enabled = false;
50 50
51 private IConfigSource m_Config; 51 private IConfigSource m_Config;
52 bool m_Registered = false; 52 bool m_Registered = false;
53 53
@@ -77,7 +77,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication
77 { 77 {
78 } 78 }
79 79
80 public Type ReplaceableInterface 80 public Type ReplaceableInterface
81 { 81 {
82 get { return null; } 82 get { return null; }
83 } 83 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
index 22857d0..834cbb7 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Grid
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private static bool m_Enabled = false; 49 private static bool m_Enabled = false;
50 50
51 private IConfigSource m_Config; 51 private IConfigSource m_Config;
52 bool m_Registered = false; 52 bool m_Registered = false;
53 53
@@ -77,7 +77,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Grid
77 { 77 {
78 } 78 }
79 79
80 public Type ReplaceableInterface 80 public Type ReplaceableInterface
81 { 81 {
82 get { return null; } 82 get { return null; }
83 } 83 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index f749295..4f87595 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 private static bool m_Enabled = false; 50 private static bool m_Enabled = false;
51 51
52 private IConfigSource m_Config; 52 private IConfigSource m_Config;
53 private bool m_Registered = false; 53 private bool m_Registered = false;
54 private string m_LocalServiceDll = String.Empty; 54 private string m_LocalServiceDll = String.Empty;
@@ -88,7 +88,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
88 { 88 {
89 } 89 }
90 90
91 public Type ReplaceableInterface 91 public Type ReplaceableInterface
92 { 92 {
93 get { return null; } 93 get { return null; }
94 } 94 }
@@ -130,7 +130,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
130 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); 130 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
131 131
132 m_UASHandler = new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn); 132 m_UASHandler = new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
133 133
134 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); 134 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
135 135
136 new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService", friendsConn); 136 new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService", friendsConn);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
index 0a4e736..61e37a9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private static bool m_Enabled = false; 47 private static bool m_Enabled = false;
48 48
49 private IConfigSource m_Config; 49 private IConfigSource m_Config;
50 bool m_Registered = false; 50 bool m_Registered = false;
51 51
@@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory
73 { 73 {
74 } 74 }
75 75
76 public Type ReplaceableInterface 76 public Type ReplaceableInterface
77 { 77 {
78 get { return null; } 78 get { return null; }
79 } 79 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
index 2fd21be..fb8c306 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land
84 { 84 {
85 } 85 }
86 86
87 public Type ReplaceableInterface 87 public Type ReplaceableInterface
88 { 88 {
89 get { return null; } 89 get { return null; }
90 } 90 }
@@ -126,15 +126,36 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land
126 126
127 public LandData GetLandData(UUID scopeID, ulong regionHandle, uint x, uint y, out byte regionAccess) 127 public LandData GetLandData(UUID scopeID, ulong regionHandle, uint x, uint y, out byte regionAccess)
128 { 128 {
129 m_log.DebugFormat("[LAND IN CONNECTOR]: GetLandData for {0}. Count = {1}", 129// m_log.DebugFormat("[LAND IN CONNECTOR]: GetLandData for {0}. Count = {1}",
130 regionHandle, m_Scenes.Count); 130// regionHandle, m_Scenes.Count);
131
132 uint rx = 0, ry = 0;
133 Util.RegionHandleToWorldLoc(regionHandle, out rx, out ry);
134 rx += x;
135 ry += y;
131 foreach (Scene s in m_Scenes) 136 foreach (Scene s in m_Scenes)
132 { 137 {
133 if (s.RegionInfo.RegionHandle == regionHandle) 138 uint t = s.RegionInfo.WorldLocX;
139 if( rx < t)
140 continue;
141 t += s.RegionInfo.RegionSizeX;
142 if( rx >= t)
143 continue;
144 t = s.RegionInfo.WorldLocY;
145 if( ry < t)
146 continue;
147 t += s.RegionInfo.RegionSizeY;
148 if( ry < t)
134 { 149 {
135 m_log.Debug("[LAND IN CONNECTOR]: Found region to GetLandData from"); 150// m_log.Debug("[LAND IN CONNECTOR]: Found region to GetLandData from");
151 x = rx - s.RegionInfo.WorldLocX;
152 y = ry - s.RegionInfo.WorldLocY;
136 regionAccess = s.RegionInfo.AccessLevel; 153 regionAccess = s.RegionInfo.AccessLevel;
137 return s.GetLandData(x, y); 154 LandData land = s.GetLandData(x, y);
155 IDwellModule dwellModule = s.RequestModuleInterface<IDwellModule>();
156 if (dwellModule != null)
157 land.Dwell = dwellModule.GetDwell(land);
158 return land;
138 } 159 }
139 } 160 }
140 m_log.DebugFormat("[LAND IN CONNECTOR]: region handle {0} not found", regionHandle); 161 m_log.DebugFormat("[LAND IN CONNECTOR]: region handle {0} not found", regionHandle);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
index 425febd..065dd94 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Login
84 { 84 {
85 } 85 }
86 86
87 public Type ReplaceableInterface 87 public Type ReplaceableInterface
88 { 88 {
89 get { return null; } 89 get { return null; }
90 } 90 }
@@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Login
113 { 113 {
114 if (!m_Enabled) 114 if (!m_Enabled)
115 return; 115 return;
116 116
117 if (!m_Registered) 117 if (!m_Registered)
118 { 118 {
119 m_Registered = true; 119 m_Registered = true;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
index c14bce7..a75a156 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private static bool m_Enabled = false; 49 private static bool m_Enabled = false;
50 50
51 private IConfigSource m_Config; 51 private IConfigSource m_Config;
52 52
53 #region Region Module interface 53 #region Region Module interface
@@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage
75 { 75 {
76 } 76 }
77 77
78 public Type ReplaceableInterface 78 public Type ReplaceableInterface
79 { 79 {
80 get { return null; } 80 get { return null; }
81 } 81 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
index 6bf47cb..09c545c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
@@ -83,7 +83,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour
83 { 83 {
84 } 84 }
85 85
86 public Type ReplaceableInterface 86 public Type ReplaceableInterface
87 { 87 {
88 get { return null; } 88 get { return null; }
89 } 89 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
index 57d1132..7ba39d4 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
@@ -77,7 +77,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation
77 { 77 {
78 } 78 }
79 79
80 public Type ReplaceableInterface 80 public Type ReplaceableInterface
81 { 81 {
82 get { return null; } 82 get { return null; }
83 } 83 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
index 4701ee6..2e6f472 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
@@ -77,65 +77,65 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
77 { 77 {
78 get; private set; 78 get; private set;
79 } 79 }
80 80
81 public Type ReplaceableInterface 81 public Type ReplaceableInterface
82 { 82 {
83 get { return null; } 83 get { return null; }
84 } 84 }
85 85
86 public LocalUserProfilesServicesConnector() 86 public LocalUserProfilesServicesConnector()
87 { 87 {
88 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params"); 88 //m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params");
89 } 89 }
90 90
91 public LocalUserProfilesServicesConnector(IConfigSource source) 91 public LocalUserProfilesServicesConnector(IConfigSource source)
92 { 92 {
93 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly."); 93 //m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly.");
94 InitialiseService(source); 94 InitialiseService(source);
95 } 95 }
96 96
97 public void InitialiseService(IConfigSource source) 97 public void InitialiseService(IConfigSource source)
98 { 98 {
99 ConfigName = "UserProfilesService"; 99 ConfigName = "UserProfilesService";
100 100
101 // Instantiate the request handler 101 // Instantiate the request handler
102 IHttpServer Server = MainServer.Instance; 102 IHttpServer Server = MainServer.Instance;
103 103
104 IConfig config = source.Configs[ConfigName]; 104 IConfig config = source.Configs[ConfigName];
105 if (config == null) 105 if (config == null)
106 { 106 {
107 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini"); 107 //m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini");
108 return; 108 return;
109 } 109 }
110 110
111 if(!config.GetBoolean("Enabled",false)) 111 if(!config.GetBoolean("Enabled",false))
112 { 112 {
113 Enabled = false; 113 Enabled = false;
114 return; 114 return;
115 } 115 }
116 116
117 Enabled = true; 117 Enabled = true;
118 118
119 string serviceDll = config.GetString("LocalServiceModule", 119 string serviceDll = config.GetString("LocalServiceModule",
120 String.Empty); 120 String.Empty);
121 121
122 if (serviceDll == String.Empty) 122 if (serviceDll == String.Empty)
123 { 123 {
124 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: No LocalServiceModule named in section UserProfilesService"); 124 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: No LocalServiceModule named in section UserProfilesService");
125 return; 125 return;
126 } 126 }
127 127
128 Object[] args = new Object[] { source, ConfigName }; 128 Object[] args = new Object[] { source, ConfigName };
129 ServiceModule = 129 ServiceModule =
130 ServerUtils.LoadPlugin<IUserProfilesService>(serviceDll, 130 ServerUtils.LoadPlugin<IUserProfilesService>(serviceDll,
131 args); 131 args);
132 132
133 if (ServiceModule == null) 133 if (ServiceModule == null)
134 { 134 {
135 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: Can't load user profiles service"); 135 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: Can't load user profiles service");
136 return; 136 return;
137 } 137 }
138 138
139 Enabled = true; 139 Enabled = true;
140 140
141 JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule); 141 JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule);
@@ -196,7 +196,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
196 { 196 {
197 if (!Enabled) 197 if (!Enabled)
198 return; 198 return;
199 199
200 lock (regions) 200 lock (regions)
201 { 201 {
202 if (regions.ContainsKey(scene.RegionInfo.RegionID)) 202 if (regions.ContainsKey(scene.RegionInfo.RegionID))
@@ -209,7 +209,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
209 void IRegionModuleBase.RemoveRegion(Scene scene) 209 void IRegionModuleBase.RemoveRegion(Scene scene)
210 { 210 {
211 if (!Enabled) 211 if (!Enabled)
212 return; 212 return;
213 213
214 lock (regions) 214 lock (regions)
215 { 215 {
@@ -221,8 +221,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
221 void IRegionModuleBase.RegionLoaded(Scene scene) 221 void IRegionModuleBase.RegionLoaded(Scene scene)
222 { 222 {
223 if (!Enabled) 223 if (!Enabled)
224 return; 224 return;
225 } 225 }
226 #endregion 226 #endregion
227 } 227 }
228} \ No newline at end of file 228}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/LocalAgentPreferencesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/LocalAgentPreferencesServiceConnector.cs
index 41ae53f..5cd68d9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/LocalAgentPreferencesServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/LocalAgentPreferencesServiceConnector.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.AgentPreferences
50 50
51 #region ISharedRegionModule 51 #region ISharedRegionModule
52 52
53 public Type ReplaceableInterface 53 public Type ReplaceableInterface
54 { 54 {
55 get { return null; } 55 get { return null; }
56 } 56 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/RemoteAgentPreferencesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/RemoteAgentPreferencesServiceConnector.cs
index ad9544a..d60236a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/RemoteAgentPreferencesServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/AgentPreferences/RemoteAgentPreferencesServiceConnector.cs
@@ -44,14 +44,14 @@ using Nini.Config;
44namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.AgentPreferences 44namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.AgentPreferences
45{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteAgentPreferencesServicesConnector")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteAgentPreferencesServicesConnector")]
47 public class RemoteAgentPreferencesServicesConnector : AgentPreferencesServicesConnector, 47 public class RemoteAgentPreferencesServicesConnector : AgentPreferencesServicesConnector,
48 ISharedRegionModule, IAgentPreferencesService 48 ISharedRegionModule, IAgentPreferencesService
49 { 49 {
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 53
54 public Type ReplaceableInterface 54 public Type ReplaceableInterface
55 { 55 {
56 get { return null; } 56 get { return null; }
57 } 57 }
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.AgentPreferences
61 get { return "RemoteAgentPreferencesServicesConnector"; } 61 get { return "RemoteAgentPreferencesServicesConnector"; }
62 } 62 }
63 63
64 public override void Initialise(IConfigSource source) 64 public new void Initialise(IConfigSource source)
65 { 65 {
66 IConfig moduleConfig = source.Configs["Modules"]; 66 IConfig moduleConfig = source.Configs["Modules"];
67 if (moduleConfig != null) 67 if (moduleConfig != null)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index 7fcfc74..92ae36f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
48 LogManager.GetLogger( 48 LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType); 49 MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private IImprovedAssetCache m_Cache = null; 51 private IAssetCache m_Cache = null;
52 private IAssetService m_GridService; 52 private IAssetService m_GridService;
53 private IAssetService m_HGService; 53 private IAssetService m_HGService;
54 54
@@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
59 59
60 private AssetPermissions m_AssetPerms; 60 private AssetPermissions m_AssetPerms;
61 61
62 public Type ReplaceableInterface 62 public Type ReplaceableInterface
63 { 63 {
64 get { return null; } 64 get { return null; }
65 } 65 }
@@ -159,7 +159,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
159 { 159 {
160 if (!m_Enabled) 160 if (!m_Enabled)
161 return; 161 return;
162 162
163 m_aScene = scene; 163 m_aScene = scene;
164 164
165 m_aScene.RegisterModuleInterface<IAssetService>(this); 165 m_aScene.RegisterModuleInterface<IAssetService>(this);
@@ -176,10 +176,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
176 176
177 if (m_Cache == null) 177 if (m_Cache == null)
178 { 178 {
179 m_Cache = scene.RequestModuleInterface<IImprovedAssetCache>(); 179 m_Cache = scene.RequestModuleInterface<IAssetCache>();
180 180
181 if (!(m_Cache is ISharedRegionModule)) 181 if (!(m_Cache is ISharedRegionModule))
182 m_Cache = null; 182 m_Cache = null;
183
183 } 184 }
184 185
185 m_log.InfoFormat("[HG ASSET CONNECTOR]: Enabled hypergrid asset broker for region {0}", scene.RegionInfo.RegionName); 186 m_log.InfoFormat("[HG ASSET CONNECTOR]: Enabled hypergrid asset broker for region {0}", scene.RegionInfo.RegionName);
@@ -205,10 +206,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
205 { 206 {
206 //m_log.DebugFormat("[HG ASSET CONNECTOR]: Get {0}", id); 207 //m_log.DebugFormat("[HG ASSET CONNECTOR]: Get {0}", id);
207 AssetBase asset = null; 208 AssetBase asset = null;
208 209
209 if (m_Cache != null) 210 if (m_Cache != null)
210 { 211 {
211 asset = m_Cache.Get(id); 212 if (!m_Cache.Get(id, out asset))
213 return null;
212 214
213 if (asset != null) 215 if (asset != null)
214 return asset; 216 return asset;
@@ -237,20 +239,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
237 239
238 public AssetBase GetCached(string id) 240 public AssetBase GetCached(string id)
239 { 241 {
242 AssetBase asset = null;
240 if (m_Cache != null) 243 if (m_Cache != null)
241 return m_Cache.Get(id); 244 m_Cache.Get(id, out asset);
242 245
243 return null; 246 return asset;
244 } 247 }
245 248
246 public AssetMetadata GetMetadata(string id) 249 public AssetMetadata GetMetadata(string id)
247 { 250 {
248 AssetBase asset = null; 251 AssetBase asset = null;
249 252
250 if (m_Cache != null) 253 if (m_Cache != null)
251 { 254 {
252 if (m_Cache != null) 255 if (!m_Cache.Get(id, out asset))
253 m_Cache.Get(id); 256 return null;
254 257
255 if (asset != null) 258 if (asset != null)
256 return asset.Metadata; 259 return asset.Metadata;
@@ -269,11 +272,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
269 public byte[] GetData(string id) 272 public byte[] GetData(string id)
270 { 273 {
271 AssetBase asset = null; 274 AssetBase asset = null;
272 275
273 if (m_Cache != null) 276 if (m_Cache != null)
274 { 277 {
275 if (m_Cache != null) 278 if (!m_Cache.Get(id, out asset))
276 m_Cache.Get(id); 279 return null;
277 280
278 if (asset != null) 281 if (asset != null)
279 return asset.Data; 282 return asset.Data;
@@ -289,9 +292,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
289 public bool Get(string id, Object sender, AssetRetrieved handler) 292 public bool Get(string id, Object sender, AssetRetrieved handler)
290 { 293 {
291 AssetBase asset = null; 294 AssetBase asset = null;
292 295
293 if (m_Cache != null) 296 if (m_Cache != null)
294 asset = m_Cache.Get(id); 297 {
298 if (!m_Cache.Get(id, out asset))
299 return false;
300 }
295 301
296 if (asset != null) 302 if (asset != null)
297 { 303 {
@@ -338,23 +344,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
338 344
339 public string Store(AssetBase asset) 345 public string Store(AssetBase asset)
340 { 346 {
341 bool isHG = IsHG(asset.ID); 347 if (asset.Local || asset.Temporary)
342
343 if ((m_Cache != null) && !isHG)
344 // Don't store it in the cache if the asset is to
345 // be sent to the other grid, because this is already
346 // a copy of the local asset.
347 m_Cache.Cache(asset);
348
349 if (asset.Local)
350 { 348 {
351 if (m_Cache != null) 349 if (m_Cache != null)
352 m_Cache.Cache(asset); 350 m_Cache.Cache(asset);
353 return asset.ID; 351 return asset.ID;
354 } 352 }
355 353
354 bool isHG = IsHG(asset.ID);
355 if ((m_Cache != null) && !isHG)
356 // Don't store it in the cache if the asset is to
357 // be sent to the other grid, because this is already
358 // a copy of the local asset.
359 m_Cache.Cache(asset);
360
356 string id; 361 string id;
357 if (IsHG(asset.ID)) 362 if (isHG)
358 { 363 {
359 if (m_AssetPerms.AllowedExport(asset.Type)) 364 if (m_AssetPerms.AllowedExport(asset.Type))
360 id = m_HGService.Store(asset); 365 id = m_HGService.Store(asset);
@@ -366,21 +371,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
366 371
367 if (String.IsNullOrEmpty(id)) 372 if (String.IsNullOrEmpty(id))
368 return string.Empty; 373 return string.Empty;
369
370 asset.ID = id;
371 374
372 if (m_Cache != null) 375 if(asset.ID != id)
373 m_Cache.Cache(asset); 376 {
377 asset.ID = id;
378 if (m_Cache != null)
379 m_Cache.Cache(asset);
380 }
374 381
375 return id; 382 return id;
376 } 383 }
377 384
378 public bool UpdateContent(string id, byte[] data) 385 public bool UpdateContent(string id, byte[] data)
379 { 386 {
380 AssetBase asset = null; 387 AssetBase asset = null;
381 388
382 if (m_Cache != null) 389 if (m_Cache != null)
383 asset = m_Cache.Get(id); 390 m_Cache.Get(id, out asset);
384 391
385 if (asset != null) 392 if (asset != null)
386 { 393 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 5f34450..37a48bb 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -44,13 +44,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
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 private IImprovedAssetCache m_Cache = null; 47 private IAssetCache m_Cache = null;
48 48
49 private IAssetService m_AssetService; 49 private IAssetService m_AssetService;
50 50
51 private bool m_Enabled = false; 51 private bool m_Enabled = false;
52 52
53 public Type ReplaceableInterface 53 public Type ReplaceableInterface
54 { 54 {
55 get { return null; } 55 get { return null; }
56 } 56 }
@@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
128 128
129 if (m_Cache == null) 129 if (m_Cache == null)
130 { 130 {
131 m_Cache = scene.RequestModuleInterface<IImprovedAssetCache>(); 131 m_Cache = scene.RequestModuleInterface<IAssetCache>();
132 132
133 if (!(m_Cache is ISharedRegionModule)) 133 if (!(m_Cache is ISharedRegionModule))
134 m_Cache = null; 134 m_Cache = null;
@@ -155,10 +155,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
155 public AssetBase Get(string id) 155 public AssetBase Get(string id)
156 { 156 {
157// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Synchronously requesting asset {0}", id); 157// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Synchronously requesting asset {0}", id);
158 158
159 AssetBase asset = null; 159 AssetBase asset = null;
160 if (m_Cache != null) 160 if (m_Cache != null)
161 asset = m_Cache.Get(id); 161 {
162 if (!m_Cache.Get(id, out asset))
163 return null;
164 }
162 165
163 if (asset == null) 166 if (asset == null)
164 { 167 {
@@ -169,7 +172,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
169// if (null == asset) 172// if (null == asset)
170// m_log.WarnFormat("[LOCAL ASSET SERVICES CONNECTOR]: Could not synchronously find asset with id {0}", id); 173// m_log.WarnFormat("[LOCAL ASSET SERVICES CONNECTOR]: Could not synchronously find asset with id {0}", id);
171 } 174 }
172 175
173 return asset; 176 return asset;
174 } 177 }
175 178
@@ -177,23 +180,27 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
177 { 180 {
178// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Cache request for {0}", id); 181// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Cache request for {0}", id);
179 182
183 AssetBase asset = null;
180 if (m_Cache != null) 184 if (m_Cache != null)
181 return m_Cache.Get(id); 185 m_Cache.Get(id, out asset);
182 186
183 return null; 187 return asset;
184 } 188 }
185 189
186 public AssetMetadata GetMetadata(string id) 190 public AssetMetadata GetMetadata(string id)
187 { 191 {
188 AssetBase asset = null; 192 AssetBase asset = null;
189 if (m_Cache != null) 193 if (m_Cache != null)
190 asset = m_Cache.Get(id); 194 {
195 if (!m_Cache.Get(id, out asset))
196 return null;
197 }
191 198
192 if (asset != null) 199 if (asset != null)
193 return asset.Metadata; 200 return asset.Metadata;
194 201
195 asset = m_AssetService.Get(id); 202 asset = m_AssetService.Get(id);
196 if (asset != null) 203 if (asset != null)
197 { 204 {
198 if (m_Cache != null) 205 if (m_Cache != null)
199 m_Cache.Cache(asset); 206 m_Cache.Cache(asset);
@@ -210,7 +217,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
210 AssetBase asset = null; 217 AssetBase asset = null;
211 218
212 if (m_Cache != null) 219 if (m_Cache != null)
213 asset = m_Cache.Get(id); 220 {
221 if (!m_Cache.Get(id, out asset))
222 return null;
223 }
214 224
215 if (asset != null) 225 if (asset != null)
216 return asset.Data; 226 return asset.Data;
@@ -229,10 +239,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
229 public bool Get(string id, Object sender, AssetRetrieved handler) 239 public bool Get(string id, Object sender, AssetRetrieved handler)
230 { 240 {
231// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Asynchronously requesting asset {0}", id); 241// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Asynchronously requesting asset {0}", id);
232 242
233 if (m_Cache != null) 243 if (m_Cache != null)
234 { 244 {
235 AssetBase asset = m_Cache.Get(id); 245 AssetBase asset;
246 if (!m_Cache.Get(id, out asset))
247 return false;
236 248
237 if (asset != null) 249 if (asset != null)
238 { 250 {
@@ -264,7 +276,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
264 { 276 {
265 if (m_Cache != null) 277 if (m_Cache != null)
266 m_Cache.Cache(asset); 278 m_Cache.Cache(asset);
267 279
268 if (asset.Local) 280 if (asset.Local)
269 { 281 {
270// m_log.DebugFormat( 282// m_log.DebugFormat(
@@ -278,7 +290,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
278// m_log.DebugFormat( 290// m_log.DebugFormat(
279// "[LOCAL ASSET SERVICE CONNECTOR]: Passing {0} {1} on to asset service for storage, status Temporary = {2}, Local = {3}", 291// "[LOCAL ASSET SERVICE CONNECTOR]: Passing {0} {1} on to asset service for storage, status Temporary = {2}, Local = {3}",
280// asset.Name, asset.ID, asset.Temporary, asset.Local); 292// asset.Name, asset.ID, asset.Temporary, asset.Local);
281 293
282 return m_AssetService.Store(asset); 294 return m_AssetService.Store(asset);
283 } 295 }
284 } 296 }
@@ -287,7 +299,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
287 { 299 {
288 AssetBase asset = null; 300 AssetBase asset = null;
289 if (m_Cache != null) 301 if (m_Cache != null)
290 m_Cache.Get(id); 302 m_Cache.Get(id, out asset);
291 if (asset != null) 303 if (asset != null)
292 { 304 {
293 asset.Data = data; 305 asset.Data = data;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
index e6eeacf..1225ab5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
@@ -48,9 +48,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
48 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private bool m_Enabled = false; 50 private bool m_Enabled = false;
51 private IImprovedAssetCache m_Cache; 51 private IAssetCache m_Cache;
52 52
53 public Type ReplaceableInterface 53 public Type ReplaceableInterface
54 { 54 {
55 get { return null; } 55 get { return null; }
56 } 56 }
@@ -111,7 +111,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
111 111
112 if (m_Cache == null) 112 if (m_Cache == null)
113 { 113 {
114 m_Cache = scene.RequestModuleInterface<IImprovedAssetCache>(); 114 m_Cache = scene.RequestModuleInterface<IAssetCache>();
115 115
116 // Since we are a shared module and scene data is not 116 // Since we are a shared module and scene data is not
117 // available for every method, the cache must be shared, too 117 // available for every method, the cache must be shared, too
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
index 16f42a7..8017245 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
53 53
54 #region ISharedRegionModule 54 #region ISharedRegionModule
55 55
56 public Type ReplaceableInterface 56 public Type ReplaceableInterface
57 { 57 {
58 get { return null; } 58 get { return null; }
59 } 59 }
@@ -139,10 +139,17 @@ 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
145 return string.Empty; 152 return string.Empty;
146 } 153 }
147 154
148 public bool Verify(UUID principalID, string token, int lifetime) 155 public bool Verify(UUID principalID, string token, int lifetime)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs
index 7cb8b22..fd1d802 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
47 47
48 private bool m_Enabled = false; 48 private bool m_Enabled = false;
49 49
50 public Type ReplaceableInterface 50 public Type ReplaceableInterface
51 { 51 {
52 get { return null; } 52 get { return null; }
53 } 53 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs
index 93dff1f..c910422 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/AuthorizationService.cs
@@ -69,7 +69,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
69 69
70 if (config != null) 70 if (config != null)
71 { 71 {
72 string accessStr = config.GetString("Region_" + scene.RegionInfo.RegionName.Replace(' ', '_'), String.Empty); 72 string defaultAccess = config.GetString("DefaultRegionAccess", "None");
73 string accessStr = config.GetString("Region_" + scene.RegionInfo.RegionName.Replace(' ', '_'), defaultAccess);
73 if (accessStr != string.Empty) 74 if (accessStr != string.Empty)
74 { 75 {
75 try 76 try
@@ -87,8 +88,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
87 } 88 }
88 89
89 public bool IsAuthorizedForRegion( 90 public bool IsAuthorizedForRegion(
90 string user, string firstName, string lastName, string regionID, out string message) 91 string user, string firstName, string lastName, string regionID, out string message, out bool isLocal)
91 { 92 {
93 UUID userID = new UUID(user);
94 isLocal = m_UserManagement.IsLocalGridUser(userID);
95
92 // This should not happen 96 // This should not happen
93 if (m_Scene.RegionInfo.RegionID.ToString() != regionID) 97 if (m_Scene.RegionInfo.RegionID.ToString() != regionID)
94 { 98 {
@@ -104,11 +108,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
104 return true; 108 return true;
105 } 109 }
106 110
107 UUID userID = new UUID(user);
108 111
109 if ((m_accessValue & AccessFlags.DisallowForeigners) != 0) 112 if ((m_accessValue & AccessFlags.DisallowForeigners) != 0)
110 { 113 {
111 if (!m_UserManagement.IsLocalGridUser(userID)) 114 if (!isLocal)
112 { 115 {
113 message = "No foreign users allowed in this region"; 116 message = "No foreign users allowed in this region";
114 return false; 117 return false;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs
index 1acb695..b2be907 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
53 53
54 private bool m_Enabled = false; 54 private bool m_Enabled = false;
55 55
56 public Type ReplaceableInterface 56 public Type ReplaceableInterface
57 { 57 {
58 get { return null; } 58 get { return null; }
59 } 59 }
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
66 public void Initialise(IConfigSource source) 66 public void Initialise(IConfigSource source)
67 { 67 {
68 m_log.Info("[AUTHORIZATION CONNECTOR]: Initialise"); 68 m_log.Info("[AUTHORIZATION CONNECTOR]: Initialise");
69 69
70 IConfig moduleConfig = source.Configs["Modules"]; 70 IConfig moduleConfig = source.Configs["Modules"];
71 if (moduleConfig != null) 71 if (moduleConfig != null)
72 { 72 {
@@ -114,13 +114,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
114 } 114 }
115 115
116 public bool IsAuthorizedForRegion( 116 public bool IsAuthorizedForRegion(
117 string userID, string firstName, string lastName, string regionID, out string message) 117 string userID, string firstName, string lastName, string regionID, out string message, out bool isLocal)
118 { 118 {
119 message = ""; 119 message = "";
120 isLocal = false;
120 if (!m_Enabled) 121 if (!m_Enabled)
121 return true; 122 return true;
122 123
123 return m_AuthorizationService.IsAuthorizedForRegion(userID, firstName, lastName, regionID, out message); 124 return m_AuthorizationService.IsAuthorizedForRegion(userID, firstName, lastName, regionID, out message, out isLocal);
124 } 125 }
125 } 126 }
126} \ No newline at end of file 127} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs
index b8d409d..3df3288 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
51 private bool m_Enabled = false; 51 private bool m_Enabled = false;
52 private List<Scene> m_scenes = new List<Scene>(); 52 private List<Scene> m_scenes = new List<Scene>();
53 53
54 public Type ReplaceableInterface 54 public Type ReplaceableInterface
55 { 55 {
56 get { return null; } 56 get { return null; }
57 } 57 }
@@ -103,7 +103,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
103 m_scenes.Add(scene); 103 m_scenes.Add(scene);
104 scene.RegisterModuleInterface<IAuthorizationService>(this); 104 scene.RegisterModuleInterface<IAuthorizationService>(this);
105 } 105 }
106 106
107 } 107 }
108 108
109 public void RemoveRegion(Scene scene) 109 public void RemoveRegion(Scene scene)
@@ -118,16 +118,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
118 m_log.InfoFormat("[REMOTE AUTHORIZATION CONNECTOR]: Enabled remote authorization for region {0}", scene.RegionInfo.RegionName); 118 m_log.InfoFormat("[REMOTE AUTHORIZATION CONNECTOR]: Enabled remote authorization for region {0}", scene.RegionInfo.RegionName);
119 119
120 } 120 }
121 121
122 public bool IsAuthorizedForRegion( 122 public bool IsAuthorizedForRegion(
123 string userID, string firstName, string lastName, string regionID, out string message) 123 string userID, string firstName, string lastName, string regionID, out string message, out bool isLocal)
124 { 124 {
125 m_log.InfoFormat( 125 m_log.InfoFormat(
126 "[REMOTE AUTHORIZATION CONNECTOR]: IsAuthorizedForRegion checking {0} for region {1}", userID, regionID); 126 "[REMOTE AUTHORIZATION CONNECTOR]: IsAuthorizedForRegion checking {0} for region {1}", userID, regionID);
127 127
128 bool isAuthorized = true; 128 bool isAuthorized = true;
129 message = String.Empty; 129 message = String.Empty;
130 130
131 // get the scene this call is being made for 131 // get the scene this call is being made for
132 Scene scene = null; 132 Scene scene = null;
133 lock (m_scenes) 133 lock (m_scenes)
@@ -140,11 +140,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
140 } 140 }
141 } 141 }
142 } 142 }
143 143
144 isLocal = false;
144 if (scene != null) 145 if (scene != null)
145 { 146 {
146 string mail = String.Empty; 147 string mail = String.Empty;
147 148
148 UserAccount account = scene.UserAccountService.GetUserAccount(UUID.Zero, new UUID(userID)); 149 UserAccount account = scene.UserAccountService.GetUserAccount(UUID.Zero, new UUID(userID));
149 150
150 //if account not found, we assume its a foreign visitor from HG, else use account data... 151 //if account not found, we assume its a foreign visitor from HG, else use account data...
@@ -153,6 +154,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
153 mail = account.Email; 154 mail = account.Email;
154 firstName = account.FirstName; 155 firstName = account.FirstName;
155 lastName = account.LastName; 156 lastName = account.LastName;
157 isLocal = true;
156 } 158 }
157 159
158 isAuthorized 160 isAuthorized
@@ -165,7 +167,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
165 "[REMOTE AUTHORIZATION CONNECTOR] IsAuthorizedForRegion, can't find scene to match region id of {0}", 167 "[REMOTE AUTHORIZATION CONNECTOR] IsAuthorizedForRegion, can't find scene to match region id of {0}",
166 regionID); 168 regionID);
167 } 169 }
168 170
169 return isAuthorized; 171 return isAuthorized;
170 } 172 }
171 } 173 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs
index c3ef588..42f6c3f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar
54 54
55 #region ISharedRegionModule 55 #region ISharedRegionModule
56 56
57 public Type ReplaceableInterface 57 public Type ReplaceableInterface
58 { 58 {
59 get { return null; } 59 get { return null; }
60 } 60 }
@@ -144,12 +144,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar
144 { 144 {
145 return m_AvatarService.GetAppearance(userID); 145 return m_AvatarService.GetAppearance(userID);
146 } 146 }
147 147
148 public bool SetAppearance(UUID userID, AvatarAppearance appearance) 148 public bool SetAppearance(UUID userID, AvatarAppearance appearance)
149 { 149 {
150 return m_AvatarService.SetAppearance(userID,appearance); 150 return m_AvatarService.SetAppearance(userID,appearance);
151 } 151 }
152 152
153 public AvatarData GetAvatar(UUID userID) 153 public AvatarData GetAvatar(UUID userID)
154 { 154 {
155 return m_AvatarService.GetAvatar(userID); 155 return m_AvatarService.GetAvatar(userID);
@@ -174,7 +174,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar
174 { 174 {
175 return m_AvatarService.RemoveItems(userID, names); 175 return m_AvatarService.RemoveItems(userID, names);
176 } 176 }
177 177
178 #endregion 178 #endregion
179 179
180 } 180 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs
index a087aea..37cfbbc 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar
47 47
48 private bool m_Enabled = false; 48 private bool m_Enabled = false;
49 49
50 public Type ReplaceableInterface 50 public Type ReplaceableInterface
51 { 51 {
52 get { return null; } 52 get { return null; }
53 } 53 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 1f782f5..d220568 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
51 private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]"; 51 private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]";
52 52
53 private IGridService m_GridService; 53 private IGridService m_GridService;
54 private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>(); 54 private RegionInfoCache m_RegionInfoCache;
55 private HashSet<Scene> m_scenes = new HashSet<Scene>();
55 56
56 private bool m_Enabled; 57 private bool m_Enabled;
57 58
@@ -63,12 +64,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
63 public LocalGridServicesConnector(IConfigSource source) 64 public LocalGridServicesConnector(IConfigSource source)
64 { 65 {
65 m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader); 66 m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader);
66 InitialiseService(source); 67 InitialiseService(source, null);
68 }
69
70 public LocalGridServicesConnector(IConfigSource source, RegionInfoCache regionInfoCache)
71 {
72 m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly with cache.", LogHeader);
73 InitialiseService(source, regionInfoCache);
67 } 74 }
68 75
69 #region ISharedRegionModule 76 #region ISharedRegionModule
70 77
71 public Type ReplaceableInterface 78 public Type ReplaceableInterface
72 { 79 {
73 get { return null; } 80 get { return null; }
74 } 81 }
@@ -86,19 +93,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
86 string name = moduleConfig.GetString("GridServices", ""); 93 string name = moduleConfig.GetString("GridServices", "");
87 if (name == Name) 94 if (name == Name)
88 { 95 {
89 InitialiseService(source); 96 if(InitialiseService(source, null))
90 m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled"); 97 m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled");
91 } 98 }
92 } 99 }
93 } 100 }
94 101
95 private void InitialiseService(IConfigSource source) 102 private bool InitialiseService(IConfigSource source, RegionInfoCache ric)
96 { 103 {
104 if(ric == null && m_RegionInfoCache == null)
105 m_RegionInfoCache = new RegionInfoCache();
106 else
107 m_RegionInfoCache = ric;
108
97 IConfig config = source.Configs["GridService"]; 109 IConfig config = source.Configs["GridService"];
98 if (config == null) 110 if (config == null)
99 { 111 {
100 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini"); 112 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini");
101 return; 113 return false;
102 } 114 }
103 115
104 string serviceDll = config.GetString("LocalServiceModule", String.Empty); 116 string serviceDll = config.GetString("LocalServiceModule", String.Empty);
@@ -106,7 +118,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
106 if (serviceDll == String.Empty) 118 if (serviceDll == String.Empty)
107 { 119 {
108 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService"); 120 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService");
109 return; 121 return false;
110 } 122 }
111 123
112 Object[] args = new Object[] { source }; 124 Object[] args = new Object[] { source };
@@ -117,19 +129,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
117 if (m_GridService == null) 129 if (m_GridService == null)
118 { 130 {
119 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service"); 131 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service");
120 return; 132 return false;
121 } 133 }
122 134
123 m_Enabled = true; 135 m_Enabled = true;
136 return true;
124 } 137 }
125 138
126 public void PostInitialise() 139 public void PostInitialise()
127 { 140 {
128 // FIXME: We will still add this command even if we aren't enabled since RemoteGridServiceConnector
129 // will have instantiated us directly.
130 MainConsole.Instance.Commands.AddCommand("Regions", false, "show neighbours",
131 "show neighbours",
132 "Shows the local regions' neighbours", HandleShowNeighboursCommand);
133 } 141 }
134 142
135 public void Close() 143 public void Close()
@@ -141,15 +149,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
141 if (!m_Enabled) 149 if (!m_Enabled)
142 return; 150 return;
143 151
144 scene.RegisterModuleInterface<IGridService>(this); 152 lock(m_scenes)
145
146 lock (m_LocalCache)
147 { 153 {
148 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID)) 154 if(!m_scenes.Contains(scene))
149 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!"); 155 m_scenes.Add(scene);
150 else
151 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
152 } 156 }
157 scene.RegisterModuleInterface<IGridService>(this);
158
159 GridRegion r = new GridRegion(scene.RegionInfo);
160 m_RegionInfoCache.CacheLocal(r);
161
162 scene.EventManager.OnRegionUp += OnRegionUp;
153 } 163 }
154 164
155 public void RemoveRegion(Scene scene) 165 public void RemoveRegion(Scene scene)
@@ -157,11 +167,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
157 if (!m_Enabled) 167 if (!m_Enabled)
158 return; 168 return;
159 169
160 lock (m_LocalCache) 170 lock(m_scenes)
161 { 171 {
162 m_LocalCache[scene.RegionInfo.RegionID].Clear(); 172 if(m_scenes.Contains(scene))
163 m_LocalCache.Remove(scene.RegionInfo.RegionID); 173 m_scenes.Remove(scene);
164 } 174 }
175
176 m_RegionInfoCache.Remove(scene.RegionInfo.ScopeID, scene.RegionInfo.RegionHandle);
177 scene.EventManager.OnRegionUp -= OnRegionUp;
165 } 178 }
166 179
167 public void RegionLoaded(Scene scene) 180 public void RegionLoaded(Scene scene)
@@ -172,6 +185,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
172 185
173 #region IGridService 186 #region IGridService
174 187
188 private void OnRegionUp(GridRegion region)
189 {
190 // This shouldn't happen
191 if (region == null)
192 return;
193
194 m_RegionInfoCache.CacheNearNeighbour(region.ScopeID, region);
195 }
196
175 public string RegisterRegion(UUID scopeID, GridRegion regionInfo) 197 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
176 { 198 {
177 return m_GridService.RegisterRegion(scopeID, regionInfo); 199 return m_GridService.RegisterRegion(scopeID, regionInfo);
@@ -184,12 +206,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
184 206
185 public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID) 207 public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
186 { 208 {
187 return m_GridService.GetNeighbours(scopeID, regionID); 209 return m_GridService.GetNeighbours(scopeID, regionID);
188 } 210 }
189 211
190 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) 212 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
191 { 213 {
192 return m_GridService.GetRegionByUUID(scopeID, regionID); 214 bool inCache = false;
215 GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache);
216 if (inCache)
217 return rinfo;
218
219 rinfo = m_GridService.GetRegionByUUID(scopeID, regionID);
220 if(rinfo != null)
221 m_RegionInfoCache.Cache(scopeID, rinfo);
222 return rinfo;
193 } 223 }
194 224
195 // Get a region given its base coordinates. 225 // Get a region given its base coordinates.
@@ -197,59 +227,30 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
197 // be the base coordinate of the region. 227 // be the base coordinate of the region.
198 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 228 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
199 { 229 {
200 GridRegion region = null;
201 uint regionX = Util.WorldToRegionLoc((uint)x);
202 uint regionY = Util.WorldToRegionLoc((uint)y);
203 230
204 // Sanity check 231 bool inCache = false;
205 if ((Util.RegionToWorldLoc(regionX) != (uint)x) || (Util.RegionToWorldLoc(regionY) != (uint)y)) 232 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, (uint)x, (uint)y, out inCache);
206 { 233 if (inCache)
207 m_log.WarnFormat("{0} GetRegionByPosition. Bad position requested: not the base of the region. Requested Pos=<{1},{2}>, Should Be=<{3},{4}>", 234 return rinfo;
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.
212 // Neighbour data is cached in memory, so this is fast
213
214 lock (m_LocalCache)
215 {
216 foreach (RegionCache rcache in m_LocalCache.Values)
217 {
218 region = rcache.GetRegionByPosition(x, y);
219 if (region != null)
220 {
221 m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>",
222 LogHeader, region.RegionName, rcache.RegionName,
223 Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
224 break;
225 }
226 }
227 }
228 235
229 // Then try on this sim (may be a lookup in DB if this is using MySql). 236 // Then try on this sim (may be a lookup in DB if this is using MySql).
230 if (region == null) 237 rinfo = m_GridService.GetRegionByPosition(scopeID, x, y);
231 { 238 if(rinfo != null)
232 region = m_GridService.GetRegionByPosition(scopeID, x, y); 239 m_RegionInfoCache.Cache(scopeID, rinfo);
233 240 return rinfo;
234 if (region == null)
235 {
236 m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>",
237 LogHeader, regionX, regionY);
238 }
239 else
240 {
241 m_log.DebugFormat("{0} GetRegionByPosition. Got region {1} from grid service. Pos=<{2},{3}>",
242 LogHeader, region.RegionName,
243 Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
244 }
245 }
246
247 return region;
248 } 241 }
249 242
250 public GridRegion GetRegionByName(UUID scopeID, string regionName) 243 public GridRegion GetRegionByName(UUID scopeID, string regionName)
251 { 244 {
252 return m_GridService.GetRegionByName(scopeID, regionName); 245 bool inCache = false;
246 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionName, out inCache);
247 if (inCache)
248 return rinfo;
249
250 rinfo = m_GridService.GetRegionByName(scopeID, regionName);
251 if(rinfo != null)
252 m_RegionInfoCache.Cache(scopeID, rinfo);
253 return rinfo;
253 } 254 }
254 255
255 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber) 256 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
@@ -281,7 +282,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
281 { 282 {
282 return m_GridService.GetHyperlinks(scopeID); 283 return m_GridService.GetHyperlinks(scopeID);
283 } 284 }
284 285
285 public int GetRegionFlags(UUID scopeID, UUID regionID) 286 public int GetRegionFlags(UUID scopeID, UUID regionID)
286 { 287 {
287 return m_GridService.GetRegionFlags(scopeID, regionID); 288 return m_GridService.GetRegionFlags(scopeID, regionID);
@@ -294,22 +295,5 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
294 295
295 #endregion 296 #endregion
296 297
297 public void HandleShowNeighboursCommand(string module, string[] cmdparams)
298 {
299 System.Text.StringBuilder caps = new System.Text.StringBuilder();
300
301 lock (m_LocalCache)
302 {
303 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
304 {
305 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
306 List<GridRegion> regions = kvp.Value.GetNeighbours();
307 foreach (GridRegion r in regions)
308 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
309 }
310 }
311
312 MainConsole.Instance.Output(caps.ToString());
313 }
314 } 298 }
315} 299}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
deleted file mode 100644
index ae76288..0000000
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
+++ /dev/null
@@ -1,102 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Services.Interfaces;
35using GridRegion = OpenSim.Services.Interfaces.GridRegion;
36
37using OpenMetaverse;
38using log4net;
39
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
41{
42 public class RegionCache
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48 private Scene m_scene;
49 private Dictionary<ulong, GridRegion> m_neighbours = new Dictionary<ulong, GridRegion>();
50
51 public string RegionName
52 {
53 get { return m_scene.RegionInfo.RegionName; }
54 }
55
56 public RegionCache(Scene s)
57 {
58 m_scene = s;
59 m_scene.EventManager.OnRegionUp += OnRegionUp;
60 }
61
62 private void OnRegionUp(GridRegion otherRegion)
63 {
64 // This shouldn't happen
65 if (otherRegion == null)
66 return;
67
68 m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}",
69 m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY));
70
71 m_neighbours[otherRegion.RegionHandle] = otherRegion;
72 }
73
74 public void Clear()
75 {
76 m_scene.EventManager.OnRegionUp -= OnRegionUp;
77 m_neighbours.Clear();
78 }
79
80 public List<GridRegion> GetNeighbours()
81 {
82 return new List<GridRegion>(m_neighbours.Values);
83 }
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)
91 {
92 uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize;
93 uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize;
94 ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap);
95
96 if (m_neighbours.ContainsKey(handle))
97 return m_neighbours[handle];
98
99 return null;
100 }
101 }
102}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
index be8a9a2..f6fff58 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
@@ -26,6 +26,8 @@
26 */ 26 */
27using System; 27using System;
28using System.Reflection; 28using System.Reflection;
29using System.Threading;
30using System.Runtime.InteropServices;
29using System.Collections.Generic; 31using System.Collections.Generic;
30using OpenSim.Framework; 32using OpenSim.Framework;
31using OpenSim.Services.Interfaces; 33using OpenSim.Services.Interfaces;
@@ -37,82 +39,68 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
37{ 39{
38 public class RegionInfoCache 40 public class RegionInfoCache
39 { 41 {
40 private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes 42 private const float CACHE_EXPIRATION_SECONDS = 120; // 2 minutes opensim regions change a lot
41 43
42// private static readonly ILog m_log = 44// private static readonly ILog m_log =
43// LogManager.GetLogger( 45// LogManager.GetLogger(
44// MethodBase.GetCurrentMethod().DeclaringType); 46// MethodBase.GetCurrentMethod().DeclaringType);
45 47
46 internal struct ScopedRegionUUID 48 private static RegionsExpiringCache m_Cache;
49 private int numberInstances;
50
51 public RegionInfoCache()
47 { 52 {
48 public UUID m_scopeID; 53 if(m_Cache == null)
49 public UUID m_regionID; 54 m_Cache = new RegionsExpiringCache();
50 public ScopedRegionUUID(UUID scopeID, UUID regionID) 55 numberInstances++;
51 {
52 m_scopeID = scopeID;
53 m_regionID = regionID;
54 }
55 } 56 }
56 57
57 internal struct ScopedRegionName 58 public void Cache(GridRegion rinfo)
58 { 59 {
59 public UUID m_scopeID; 60 if (rinfo != null)
60 public string m_name; 61 this.Cache(rinfo.ScopeID, rinfo);
61 public ScopedRegionName(UUID scopeID, string name)
62 {
63 m_scopeID = scopeID;
64 m_name = name;
65 }
66 } 62 }
67 63
68 internal struct ScopedRegionPosition 64 public void Cache(UUID scopeID, GridRegion rinfo)
69 { 65 {
70 public UUID m_scopeID; 66 if (rinfo == null)
71 public ulong m_regionHandle; 67 return;
72 public ScopedRegionPosition(UUID scopeID, ulong handle)
73 {
74 m_scopeID = scopeID;
75 m_regionHandle = handle;
76 }
77 }
78 68
79 private ExpiringCache<ScopedRegionUUID, GridRegion> m_UUIDCache; 69 m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
80 private ExpiringCache<ScopedRegionName, ScopedRegionUUID> m_NameCache; 70 }
81 private ExpiringCache<ScopedRegionPosition, GridRegion> m_PositionCache;
82 71
83 public RegionInfoCache() 72 public void CacheLocal(GridRegion rinfo)
84 { 73 {
85 m_UUIDCache = new ExpiringCache<ScopedRegionUUID, GridRegion>(); 74 if (rinfo == null)
86 m_NameCache = new ExpiringCache<ScopedRegionName, ScopedRegionUUID>(); 75 return;
87 m_PositionCache = new ExpiringCache<ScopedRegionPosition, GridRegion>(); 76
77 m_Cache.AddOrUpdate(rinfo.ScopeID, rinfo, 1e7f);
88 } 78 }
89 79
90 public void Cache(GridRegion rinfo) 80 public void CacheNearNeighbour(UUID scopeID, GridRegion rinfo)
91 { 81 {
92 if (rinfo != null) 82 if (rinfo == null)
93 this.Cache(rinfo.ScopeID,rinfo.RegionID,rinfo); 83 return;
84
85 m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
94 } 86 }
95 87
96 public void Cache(UUID scopeID, UUID regionID, GridRegion rinfo) 88 public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds)
97 { 89 {
98 // for now, do not cache negative results; this is because
99 // we need to figure out how to handle regions coming online
100 // in a timely way
101 if (rinfo == null) 90 if (rinfo == null)
102 return; 91 return;
103
104 ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID);
105
106 // Cache even null accounts
107 m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS);
108 if (rinfo != null)
109 {
110 ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName);
111 m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS);
112 92
113 ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, rinfo.RegionHandle); 93 m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds);
114 m_PositionCache.AddOrUpdate(pos, rinfo, CACHE_EXPIRATION_SECONDS); 94 }
115 } 95
96 public void Remove(UUID scopeID, GridRegion rinfo)
97 {
98 m_Cache.Remove(scopeID, rinfo);
99 }
100
101 public void Remove(UUID scopeID, ulong regionHandle)
102 {
103 m_Cache.Remove(scopeID, regionHandle);
116 } 104 }
117 105
118 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) 106 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
@@ -120,8 +108,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
120 inCache = false; 108 inCache = false;
121 109
122 GridRegion rinfo = null; 110 GridRegion rinfo = null;
123 ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); 111 if (m_Cache.TryGetValue(scopeID, regionID, out rinfo))
124 if (m_UUIDCache.TryGetValue(id, out rinfo))
125 { 112 {
126 inCache = true; 113 inCache = true;
127 return rinfo; 114 return rinfo;
@@ -135,8 +122,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
135 inCache = false; 122 inCache = false;
136 123
137 GridRegion rinfo = null; 124 GridRegion rinfo = null;
138 ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, handle); 125 if (m_Cache.TryGetValue(scopeID, handle, out rinfo))
139 if (m_PositionCache.TryGetValue(pos, out rinfo))
140 { 126 {
141 inCache = true; 127 inCache = true;
142 return rinfo; 128 return rinfo;
@@ -145,25 +131,868 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
145 return null; 131 return null;
146 } 132 }
147 133
148
149 public GridRegion Get(UUID scopeID, string name, out bool inCache) 134 public GridRegion Get(UUID scopeID, string name, out bool inCache)
150 { 135 {
151 inCache = false; 136 inCache = false;
152 137
153 ScopedRegionName sname = new ScopedRegionName(scopeID,name); 138 GridRegion rinfo = null;
139 if (m_Cache.TryGetValue(scopeID, name, out rinfo))
140 {
141 inCache = true;
142 return rinfo;
143 }
144
145 return null;
146 }
147
148 public GridRegion Get(UUID scopeID, uint x, uint y, out bool inCache)
149 {
150 inCache = false;
151
152 GridRegion rinfo = null;
153 if (m_Cache.TryGetValue(scopeID, x, y, out rinfo))
154 {
155 inCache = true;
156 return rinfo;
157 }
158
159 return null;
160 }
161 }
162
163 // dont care about endianess
164 [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)]
165 public class fastRegionHandle
166 {
167 [FieldOffset(0)] public ulong handle;
168 [FieldOffset(0)] public uint y;
169 [FieldOffset(4)] public uint x;
170
171 public fastRegionHandle(ulong h)
172 {
173 handle = h;
174 }
175
176 public fastRegionHandle(uint px, uint py)
177 {
178 y = py & 0xffffff00;
179 x = px & 0xffffff00;
180 }
181 // actually do care
182 public ulong toHandle()
183 {
184 if(BitConverter.IsLittleEndian)
185 return handle;
186 return (ulong) x << 32 | (ulong)y ;
187 }
188
189 public static bool operator ==(fastRegionHandle value1, fastRegionHandle value2)
190 {
191 return value1.handle == value2.handle;
192 }
193 public static bool operator !=(fastRegionHandle value1, fastRegionHandle value2)
194 {
195 return value1.handle != value2.handle;
196 }
197 public override int GetHashCode()
198 {
199 return handle.GetHashCode();
200 }
201 public override bool Equals(Object obj)
202 {
203 if(obj == null)
204 return false;
205 fastRegionHandle p = obj as fastRegionHandle;
206 return p.handle == handle;
207 }
208 }
209
210/*
211 [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)]
212 public class regionHandle
213 {
214 [FieldOffset(0)] private ulong handle;
215 [FieldOffset(0)] public uint a;
216 [FieldOffset(4)] public uint b;
217
218 public regionHandle(ulong h)
219 {
220 handle = h;
221 }
222
223 public regionHandle(uint px, uint py)
224 {
225 if(BitConverter.IsLittleEndian)
226 {
227 a = py & 0xffffff00;
228 b = px & 0xffffff00;
229 }
230 else
231 {
232 a = px & 0xffffff00;
233 b = py & 0xffffff00;
234 }
235 }
236
237 public uint x
238 {
239 get
240 {
241 if(BitConverter.IsLittleEndian)
242 return b;
243 return a;
244 }
245 set
246 {
247 if(BitConverter.IsLittleEndian)
248 b = value & 0xffffff00;
249 else
250 a = value & 0xffffff00;
251 }
252 }
253
254 public uint y
255 {
256 get
257 {
258 if(BitConverter.IsLittleEndian)
259 return a;
260 return b;
261 }
262 set
263 {
264 if(BitConverter.IsLittleEndian)
265 a = value;
266 else
267 b = value;
268 }
269 }
270
271 public static bool operator ==(regionHandle value1, regionHandle value2)
272 {
273 return value1.handle == value2.handle;
274 }
275 public static bool operator !=(regionHandle value1, regionHandle value2)
276 {
277 return value1.handle != value2.handle;
278 }
279 public override int GetHashCode()
280 {
281 return handle.GetHashCode();
282 }
283 public override bool Equals(Object obj)
284 {
285 if(obj == null)
286 return false;
287 regionHandle p = obj as regionHandle;
288 return p.handle == handle;
289 }
290 }
291*/
292
293 public class RegionInfoForScope
294 {
295 public const ulong HANDLEMASK = 0xffffff00ffffff00ul;
296 public const ulong HANDLECOORDMASK = 0xffffff00ul;
297
298 private Dictionary<ulong, GridRegion> storage;
299 private Dictionary<ulong, DateTime> expires;
300 private Dictionary<string, ulong> byname;
301 private Dictionary<UUID, ulong> byuuid;
302 // includes handles to the inside of large regions
303 private Dictionary<ulong, ulong> innerHandles = new Dictionary<ulong, ulong>();
304
305 public RegionInfoForScope()
306 {
307 storage = new Dictionary<ulong, GridRegion>();
308 expires = new Dictionary<ulong, DateTime>();
309 byname = new Dictionary<string, ulong>();
310 byuuid = new Dictionary<UUID, ulong>();
311 }
312
313 public RegionInfoForScope(GridRegion region, DateTime expire)
314 {
315 storage = new Dictionary<ulong, GridRegion>();
316 expires = new Dictionary<ulong, DateTime>();
317 byname = new Dictionary<string, ulong>();
318 byuuid = new Dictionary<UUID, ulong>();
319
320 ulong handle = region.RegionHandle & HANDLEMASK;
321 storage[handle] = region;
322 expires[handle] = expire;
323 byname[region.RegionName] = handle;
324 byuuid[region.RegionID] = handle;
325 addToInner(region);
326 }
327
328 public void Add(GridRegion region, DateTime expire)
329 {
330 ulong handle = region.RegionHandle & HANDLEMASK;
331
332 if(storage != null && storage.ContainsKey(handle))
333 return;
334
335 if(storage == null)
336 storage = new Dictionary<ulong, GridRegion>();
337 if(expires == null)
338 expires = new Dictionary<ulong, DateTime>();
339 if(byname == null)
340 byname = new Dictionary<string, ulong>();
341 if(byuuid == null)
342 byuuid = new Dictionary<UUID, ulong>();
343
344 storage[handle] = region;
345 expires[handle] = expire;
346 byname[region.RegionName] = handle;
347 byuuid[region.RegionID] = handle;
348
349 addToInner(region);
350 }
351
352 public void AddUpdate(GridRegion region, DateTime expire)
353 {
354 if(storage == null)
355 storage = new Dictionary<ulong, GridRegion>();
356 if(expires == null)
357 expires = new Dictionary<ulong, DateTime>();
358 if(byname == null)
359 byname = new Dictionary<string, ulong>();
360 if(byuuid == null)
361 byuuid = new Dictionary<UUID, ulong>();
362
363 ulong handle = region.RegionHandle & HANDLEMASK;
154 364
155 ScopedRegionUUID id; 365 if(expires.ContainsKey(handle))
156 if (m_NameCache.TryGetValue(sname, out id))
157 { 366 {
158 GridRegion rinfo = null; 367 if(expires[handle] < expire)
159 if (m_UUIDCache.TryGetValue(id, out rinfo)) 368 expires[handle] = expire;
369 if(storage.ContainsKey(handle))
160 { 370 {
161 inCache = true; 371 GridRegion oldr = storage[handle];
162 return rinfo; 372 if (oldr.RegionSizeX != region.RegionSizeX
373 || oldr.RegionSizeY != region.RegionSizeY)
374 {
375 removeFromInner(oldr);
376 addToInner(region);
377 }
163 } 378 }
164 } 379 }
165 380 else
381 {
382 expires[handle] = expire;
383 addToInner(region);
384 }
385 storage[handle] = region;
386 byname[region.RegionName] = handle;
387 byuuid[region.RegionID] = handle;
388 }
389
390 public void Remove(GridRegion region)
391 {
392 if(region == null)
393 return;
394
395 if(byname != null)
396 byname.Remove(region.RegionName);
397 if(byuuid != null)
398 byuuid.Remove(region.RegionID);
399
400 ulong handle = region.RegionHandle & HANDLEMASK;
401 if(storage != null)
402 {
403 if(storage.ContainsKey(handle))
404 {
405 storage[handle] = null;
406 storage.Remove(handle);
407 }
408 }
409 removeFromInner(region);
410 if(expires != null)
411 {
412 expires.Remove(handle);
413 if(expires.Count == 0)
414 Clear();
415 }
416 }
417
418 public void Remove(ulong handle)
419 {
420 handle &= HANDLEMASK;
421
422 if(storage != null)
423 {
424 if(storage.ContainsKey(handle))
425 {
426 GridRegion r = storage[handle];
427 if(byname != null)
428 byname.Remove(r.RegionName);
429 if(byuuid != null)
430 byuuid.Remove(r.RegionID);
431 removeFromInner(r);
432 storage[handle] = null;
433 }
434 storage.Remove(handle);
435 }
436 if(expires != null)
437 {
438 expires.Remove(handle);
439 if(expires.Count == 0)
440 Clear();
441 }
442 }
443
444 public void Clear()
445 {
446 if(expires != null)
447 expires.Clear();
448 if(storage != null)
449 storage.Clear();
450 if(byname != null)
451 byname.Clear();
452 if(byuuid != null)
453 byuuid.Clear();
454 byname = null;
455 byuuid = null;
456 storage = null;
457 expires = null;
458 innerHandles.Clear();
459 }
460
461 public bool Contains(GridRegion region)
462 {
463 if(storage == null)
464 return false;
465 if(region == null)
466 return false;
467
468 ulong handle = region.RegionHandle & HANDLEMASK;
469 return storage.ContainsKey(handle);
470 }
471
472 public bool Contains(ulong handle)
473 {
474 if(storage == null)
475 return false;
476
477 handle &= HANDLEMASK;
478 return storage.ContainsKey(handle);
479 }
480
481 public GridRegion get(ulong handle)
482 {
483 if(storage == null)
484 return null;
485
486 handle &= HANDLEMASK;
487 if(storage.ContainsKey(handle))
488 return storage[handle];
489
490 if(!innerHandles.ContainsKey(handle))
491 return null;
492
493 ulong rhandle = innerHandles[handle];
494 if(storage.ContainsKey(rhandle))
495 return storage[rhandle];
496
166 return null; 497 return null;
167 } 498 }
499
500 public GridRegion get(string name)
501 {
502 if(byname == null || !byname.ContainsKey(name))
503 return null;
504
505 ulong handle = byname[name];
506 if(storage.ContainsKey(handle))
507 return storage[handle];
508 return null;
509 }
510
511 public GridRegion get(UUID id)
512 {
513 if(byuuid == null || !byuuid.ContainsKey(id))
514 return null;
515
516 ulong handle = byuuid[id];
517 if(storage.ContainsKey(handle))
518 return storage[handle];
519 return null;
520 }
521
522 public GridRegion get(uint x, uint y)
523 {
524 if(storage == null)
525 return null;
526
527 // look for a handle first this should find normal size regions
528 ulong handle = (ulong)x & HANDLECOORDMASK;
529 handle <<= 32;
530 handle |= ((ulong)y & HANDLECOORDMASK);
531
532 if(storage.ContainsKey(handle))
533 return storage[handle];
534
535 if(!innerHandles.ContainsKey(handle))
536 return null;
537
538 ulong rhandle = innerHandles[handle];
539 if(!storage.ContainsKey(rhandle))
540 return null;
541
542 GridRegion r = storage[rhandle];
543 if(r == null)
544 return null;
545
546 // extra check, possible redundant
547
548 int test = r.RegionLocX;
549 if(x < test)
550 return null;
551 test += r.RegionSizeX;
552 if(x >= test)
553 return null;
554 test = r.RegionLocY;
555 if (y < test)
556 return null;
557 test += r.RegionSizeY;
558 if (y < test)
559 return r;
560
561/*
562 // next do the harder work
563 foreach(KeyValuePair<ulong, GridRegion> kvp in storage)
564 {
565 GridRegion r = kvp.Value;
566 if(r == null) // ??
567 continue;
568
569 int test = r.RegionLocX;
570 if(x < test)
571 continue;
572 test += r.RegionSizeX;
573 if(x >= test)
574 continue;
575 test = r.RegionLocY;
576 if (y < test)
577 continue;
578 test += r.RegionSizeY;
579 if (y < test)
580 return r;
581 }
582*/
583 return null;
584 }
585
586 public int expire(DateTime now )
587 {
588 if(expires == null || expires.Count == 0)
589 return 0;
590
591 int expiresCount = expires.Count;
592 List<ulong> toexpire = new List<ulong>();
593
594 foreach(KeyValuePair<ulong, DateTime> kvp in expires)
595 {
596 if(kvp.Value < now)
597 toexpire.Add(kvp.Key);
598 }
599
600 int toexpireCount = toexpire.Count;
601 if(toexpireCount == 0)
602 return expiresCount;
603
604 if(toexpireCount == expiresCount)
605 {
606 Clear();
607 return 0;
608 }
609
610 if(storage != null)
611 {
612 ulong h;
613 for(int i = 0; i < toexpireCount; i++)
614 {
615 h = toexpire[i];
616 if(storage.ContainsKey(h))
617 {
618 GridRegion r = storage[h];
619 if(byname != null)
620 byname.Remove(r.RegionName);
621 if(byuuid != null)
622 byuuid.Remove(r.RegionID);
623 removeFromInner(r);
624
625 storage[h] = null;
626 storage.Remove(h);
627 }
628 if(expires != null)
629 expires.Remove(h);
630 }
631 }
632 else
633 {
634 Clear();
635 return 0;
636 }
637
638 expiresCount = expires.Count;
639 if(expiresCount == 0)
640 {
641 byname = null;
642 byuuid = null;
643 storage = null;
644 expires = null;
645 return 0;
646 }
647
648 return expiresCount;
649 }
650
651 public int Count()
652 {
653 if(byname == null)
654 return 0;
655 else
656 return byname.Count;
657 }
658
659 private void addToInner(GridRegion region)
660 {
661 int rsx = region.RegionSizeX;
662 int rsy = region.RegionSizeY;
663
664 if(rsx < 512 && rsy < 512)
665 return;
666
667 rsx >>= 8;
668 rsy >>= 8;
669
670 ulong handle = region.RegionHandle & HANDLEMASK;
671 fastRegionHandle fh = new fastRegionHandle(handle);
672 uint startY = fh.y;
673 for(int i = 0; i < rsx; i++)
674 {
675 for(int j = 0; j < rsy ; j++)
676 {
677 innerHandles[fh.toHandle()] = handle;
678 fh.y += 256;
679 }
680
681 fh.y = startY;
682 fh.x += 256;
683 }
684 }
685
686 private void removeFromInner(GridRegion region)
687 {
688 int rsx = region.RegionSizeX;
689 int rsy = region.RegionSizeY;
690
691 if(rsx < 512 && rsy < 512)
692 return;
693
694 rsx >>= 8;
695 rsy >>= 8;
696 ulong handle = region.RegionHandle & HANDLEMASK;
697 fastRegionHandle fh = new fastRegionHandle(handle);
698 uint startY = fh.y;
699 for(int i = 0; i < rsx; i++)
700 {
701 for(int j = 0; j < rsy ; j++)
702 {
703 innerHandles.Remove(fh.toHandle());
704 fh.y += 256;
705 }
706
707 fh.y = startY;
708 fh.x += 256;
709 }
710 }
711 }
712
713 public class RegionsExpiringCache
714 {
715 const double CACHE_PURGE_TIME = 60000; // milliseconds
716 const int MAX_LOCK_WAIT = 10000; // milliseconds
717
718 /// <summary>For thread safety</summary>
719 object syncRoot = new object();
720 /// <summary>For thread safety</summary>
721 object isPurging = new object();
722
723 Dictionary<UUID, RegionInfoForScope> InfobyScope = new Dictionary<UUID, RegionInfoForScope>();
724 private System.Timers.Timer timer = new System.Timers.Timer(CACHE_PURGE_TIME);
725
726 public RegionsExpiringCache()
727 {
728 timer.Elapsed += PurgeCache;
729 timer.Start();
730 }
731
732 public bool AddOrUpdate(UUID scope, GridRegion region, float expirationSeconds)
733 {
734 if(region == null)
735 return false;
736
737 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
738 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
739
740 try
741 {
742 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
743
744 RegionInfoForScope ris = null;
745 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
746 {
747 ris = new RegionInfoForScope(region, expire);
748 InfobyScope[scope] = ris;
749 }
750 else
751 ris.AddUpdate(region, expire);
752
753 return true;
754 }
755 finally { Monitor.Exit(syncRoot); }
756 }
757
758 public void Clear()
759 {
760 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
761 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
762 try
763 {
764 foreach(RegionInfoForScope ris in InfobyScope.Values)
765 ris.Clear();
766 InfobyScope.Clear();
767 }
768 finally { Monitor.Exit(syncRoot); }
769 }
770
771 public bool Contains(UUID scope, GridRegion region)
772 {
773 if(region == null)
774 return false;
775
776 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
777 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
778
779 try
780 {
781 RegionInfoForScope ris = null;
782 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
783 return false;
784
785 return ris.Contains(region);
786 }
787 finally { Monitor.Exit(syncRoot); }
788 }
789
790 public bool Contains(UUID scope, ulong handle)
791 {
792 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
793 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
794
795 try
796 {
797 RegionInfoForScope ris = null;
798 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
799 return false;
800
801 return ris.Contains(handle);
802 }
803 finally { Monitor.Exit(syncRoot); }
804 }
805
806 public int Count()
807 {
808 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
809 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
810
811 try
812 {
813 int count = 0;
814 foreach(RegionInfoForScope ris in InfobyScope.Values)
815 count += ris.Count();
816 return count;
817 }
818 finally { Monitor.Exit(syncRoot); }
819 }
820
821 public bool Remove(UUID scope, ulong handle)
822 {
823 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
824 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
825 try
826 {
827 RegionInfoForScope ris = null;
828 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
829 return false;
830
831 ris.Remove(handle);
832 if(ris.Count() == 0)
833 InfobyScope.Remove(scope);
834 return true;
835 }
836 finally { Monitor.Exit(syncRoot); }
837 }
838
839 public bool Remove(UUID scope, GridRegion region)
840 {
841 if(region == null)
842 return false;
843
844 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
845 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
846 try
847 {
848 RegionInfoForScope ris = null;
849 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
850 return false;
851
852 ris.Remove(region);
853 if(ris.Count() == 0)
854 InfobyScope.Remove(scope);
855 return true;
856 }
857 finally { Monitor.Exit(syncRoot); }
858 }
859
860 public bool TryGetValue(UUID scope, ulong handle, out GridRegion value)
861 {
862 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
863 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
864
865 value = null;
866 try
867 {
868 RegionInfoForScope ris = null;
869 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
870 return false;
871 value = ris.get(handle);
872 }
873 finally { Monitor.Exit(syncRoot); }
874
875 return value != null;
876 }
877
878 public bool TryGetValue(UUID scope, string name, out GridRegion value)
879 {
880 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
881 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
882
883 value = null;
884 try
885 {
886 RegionInfoForScope ris = null;
887 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
888 return false;
889 value = ris.get(name);
890 }
891 finally { Monitor.Exit(syncRoot); }
892
893 return value != null;
894 }
895
896 public bool TryGetValue(UUID scope, UUID id, out GridRegion value)
897 {
898 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
899 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
900
901 value = null;
902 try
903 {
904 RegionInfoForScope ris = null;
905 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
906 return false;
907 value = ris.get(id);
908 }
909 finally { Monitor.Exit(syncRoot); }
910
911 return value != null;
912 }
913
914 // gets a region that contains world position (x,y)
915 // hopefull will not take ages
916 public bool TryGetValue(UUID scope, uint x, uint y, out GridRegion value)
917 {
918 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
919 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
920
921 value = null;
922 try
923 {
924 RegionInfoForScope ris = null;
925 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
926 return false;
927
928 value = ris.get(x, y);
929 }
930 finally { Monitor.Exit(syncRoot); }
931
932 return value != null;
933 }
934
935 public bool Update(UUID scope, GridRegion region, double expirationSeconds)
936 {
937 if(region == null)
938 return false;
939
940 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
941 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
942
943 try
944 {
945 RegionInfoForScope ris = null;
946 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
947 return false;
948
949 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
950 ris.AddUpdate(region,expire);
951 return true;
952 }
953 finally { Monitor.Exit(syncRoot); }
954 }
955
956 /// <summary>
957 /// Purges expired objects from the cache. Called automatically by the purge timer.
958 /// </summary>
959 private void PurgeCache(object sender, System.Timers.ElapsedEventArgs e)
960 {
961 // Only let one thread purge at once - a buildup could cause a crash
962 // This could cause the purge to be delayed while there are lots of read/write ops
963 // happening on the cache
964 if (!Monitor.TryEnter(isPurging))
965 return;
966
967 DateTime now = DateTime.UtcNow;
968
969 try
970 {
971 // If we fail to acquire a lock on the synchronization root after MAX_LOCK_WAIT, skip this purge cycle
972 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
973 return;
974 try
975 {
976 List<UUID> expiredscopes = new List<UUID>();
977
978 foreach (KeyValuePair<UUID, RegionInfoForScope> kvp in InfobyScope)
979 {
980 if (kvp.Value.expire(now) == 0)
981 expiredscopes.Add(kvp.Key);
982 }
983
984 if (expiredscopes.Count > 0)
985 {
986 foreach (UUID sid in expiredscopes)
987 {
988 InfobyScope[sid] = null;
989 InfobyScope.Remove(sid);
990 }
991 }
992 }
993 finally { Monitor.Exit(syncRoot); }
994 }
995 finally { Monitor.Exit(isPurging); }
996 }
168 } 997 }
169} 998}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index 85073fc..0efe99d 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -52,12 +52,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
52 MethodBase.GetCurrentMethod().DeclaringType); 52 MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 private bool m_Enabled = false; 54 private bool m_Enabled = false;
55 private string m_ThisGatekeeper = string.Empty;
55 56
56 private IGridService m_LocalGridService; 57 private IGridService m_LocalGridService;
57 private IGridService m_RemoteGridService; 58 private IGridService m_RemoteGridService;
58 59
59 private RegionInfoCache m_RegionInfoCache = new RegionInfoCache(); 60 private RegionInfoCache m_RegionInfoCache;
60 61
61 public RemoteGridServicesConnector() 62 public RemoteGridServicesConnector()
62 { 63 {
63 } 64 }
@@ -69,7 +70,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
69 70
70 #region ISharedRegionmodule 71 #region ISharedRegionmodule
71 72
72 public Type ReplaceableInterface 73 public Type ReplaceableInterface
73 { 74 {
74 get { return null; } 75 get { return null; }
75 } 76 }
@@ -87,38 +88,57 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
87 string name = moduleConfig.GetString("GridServices", ""); 88 string name = moduleConfig.GetString("GridServices", "");
88 if (name == Name) 89 if (name == Name)
89 { 90 {
90 InitialiseServices(source); 91 if(InitialiseServices(source))
91 m_Enabled = true; 92 {
92 m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled"); 93 m_Enabled = true;
94 m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled");
95 }
93 } 96 }
94 } 97 }
95 } 98 }
96 99
97 private void InitialiseServices(IConfigSource source) 100 private bool InitialiseServices(IConfigSource source)
98 { 101 {
99 IConfig gridConfig = source.Configs["GridService"]; 102 IConfig gridConfig = source.Configs["GridService"];
100 if (gridConfig == null) 103 if (gridConfig == null)
101 { 104 {
102 m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini"); 105 m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini");
103 return; 106 return false;
104 } 107 }
105 108
106 string networkConnector = gridConfig.GetString("NetworkConnector", string.Empty); 109 string networkConnector = gridConfig.GetString("NetworkConnector", string.Empty);
107 if (networkConnector == string.Empty) 110 if (networkConnector == string.Empty)
108 { 111 {
109 m_log.Error("[REMOTE GRID CONNECTOR]: Please specify a network connector under [GridService]"); 112 m_log.Error("[REMOTE GRID CONNECTOR]: Please specify a network connector under [GridService]");
110 return; 113 return false;
111 } 114 }
112 115
113 Object[] args = new Object[] { source }; 116 Object[] args = new Object[] { source };
114 m_RemoteGridService = ServerUtils.LoadPlugin<IGridService>(networkConnector, args); 117 m_RemoteGridService = ServerUtils.LoadPlugin<IGridService>(networkConnector, args);
115 118
116 m_LocalGridService = new LocalGridServicesConnector(source); 119 m_LocalGridService = new LocalGridServicesConnector(source, m_RegionInfoCache);
117 } 120 if (m_LocalGridService == null)
121 {
122 m_log.Error("[REMOTE GRID CONNECTOR]: failed to load local connector");
123 return false;
124 }
125
126 if(m_RegionInfoCache == null)
127 m_RegionInfoCache = new RegionInfoCache();
128
129 m_ThisGatekeeper = Util.GetConfigVarFromSections<string>(source, "GatekeeperURI",
130 new string[] { "Startup", "Hypergrid", "GridService" }, String.Empty);
131 // Legacy. Remove soon!
132//// m_ThisGatekeeper = gridConfig.GetString("Gatekeeper", m_ThisGatekeeper);
133
134 Util.checkServiceURI(m_ThisGatekeeper, out m_ThisGatekeeper);
135
136 return true;
137 }
118 138
119 public void PostInitialise() 139 public void PostInitialise()
120 { 140 {
121 if (m_LocalGridService != null) 141 if (m_Enabled)
122 ((ISharedRegionModule)m_LocalGridService).PostInitialise(); 142 ((ISharedRegionModule)m_LocalGridService).PostInitialise();
123 } 143 }
124 144
@@ -129,15 +149,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
129 public void AddRegion(Scene scene) 149 public void AddRegion(Scene scene)
130 { 150 {
131 if (m_Enabled) 151 if (m_Enabled)
152 {
132 scene.RegisterModuleInterface<IGridService>(this); 153 scene.RegisterModuleInterface<IGridService>(this);
133
134 if (m_LocalGridService != null)
135 ((ISharedRegionModule)m_LocalGridService).AddRegion(scene); 154 ((ISharedRegionModule)m_LocalGridService).AddRegion(scene);
155 }
136 } 156 }
137 157
138 public void RemoveRegion(Scene scene) 158 public void RemoveRegion(Scene scene)
139 { 159 {
140 if (m_LocalGridService != null) 160 if (m_Enabled)
141 ((ISharedRegionModule)m_LocalGridService).RemoveRegion(scene); 161 ((ISharedRegionModule)m_LocalGridService).RemoveRegion(scene);
142 } 162 }
143 163
@@ -174,16 +194,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
174 194
175 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) 195 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
176 { 196 {
177 bool inCache = false; 197 GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID);
178 GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache); 198 if (rinfo != null)
179 if (inCache)
180 return rinfo; 199 return rinfo;
181
182 rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID);
183 if (rinfo == null)
184 rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID);
185 200
186 m_RegionInfoCache.Cache(scopeID,regionID,rinfo); 201 rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID);
202 m_RegionInfoCache.Cache(scopeID, rinfo);
187 return rinfo; 203 return rinfo;
188 } 204 }
189 205
@@ -193,51 +209,56 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
193 // The coordinates are world coords (meters), NOT region units. 209 // The coordinates are world coords (meters), NOT region units.
194 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 210 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
195 { 211 {
196 ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y); 212 GridRegion rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y);
197 uint regionX = Util.WorldToRegionLoc((uint)x); 213 if (rinfo != null)
198 uint regionY = Util.WorldToRegionLoc((uint)y);
199
200 // Sanity check
201 if ((Util.RegionToWorldLoc(regionX) != (uint)x) || (Util.RegionToWorldLoc(regionY) != (uint)y))
202 { 214 {
203 m_log.WarnFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Bad position requested: not the base of the region. Requested Pos=<{0},{1}>, Should Be=<{2},{3}>", 215// m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Found region {0} on local. Pos=<{1},{2}>, RegionHandle={3}",
204 x, y, Util.RegionToWorldLoc(regionX), Util.RegionToWorldLoc(regionY)); 216// rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
205 }
206
207 bool inCache = false;
208 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache);
209 if (inCache)
210 {
211 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Found region {0} in cache. Pos=<{1},{2}>, RegionHandle={3}",
212 // (rinfo == null) ? "<missing>" : rinfo.RegionName, regionX, regionY, (rinfo == null) ? regionHandle : rinfo.RegionHandle);
213 return rinfo; 217 return rinfo;
214 } 218 }
215 219
216 rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y); 220 rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y);
217 if (rinfo == null)
218 rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y);
219 221
220 m_RegionInfoCache.Cache(rinfo); 222 if (rinfo == null)
221 223 {
222 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}", 224// uint regionX = Util.WorldToRegionLoc((uint)x);
223 // (rinfo == null) ? "<missing>" : rinfo.RegionName, regionX, regionY, (rinfo == null) ? regionHandle : rinfo.RegionHandle); 225// uint regionY = Util.WorldToRegionLoc((uint)y);
226// m_log.WarnFormat("[REMOTE GRID CONNECTOR]: Requested region {0}-{1} not found", regionX, regionY);
227 }
228 else
229 {
230 m_RegionInfoCache.Cache(scopeID, rinfo);
224 231
232// m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}",
233// rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
234 }
225 return rinfo; 235 return rinfo;
226 } 236 }
227 237
228 public GridRegion GetRegionByName(UUID scopeID, string regionName) 238 public GridRegion GetRegionByName(UUID scopeID, string name)
229 { 239 {
230 bool inCache = false; 240 GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, name);
231 GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionName, out inCache); 241 if (rinfo != null)
232 if (inCache)
233 return rinfo; 242 return rinfo;
234
235 rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName);
236 if (rinfo == null)
237 rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName);
238 243
239 // can't cache negative results for name lookups 244 // HG urls should not get here, strip them
240 m_RegionInfoCache.Cache(rinfo); 245 // side effect is that local regions with same name as HG may also be found
246 // this mb good or bad
247 string regionName = name;
248 if(name.Contains("."))
249 {
250 if(string.IsNullOrWhiteSpace(m_ThisGatekeeper))
251 return rinfo; // no HG
252
253 string regionURI = "";
254 if(!Util.buildHGRegionURI(name, out regionURI, out regionName) || string.IsNullOrWhiteSpace(regionName))
255 return rinfo; // invalid
256 if(m_ThisGatekeeper != regionURI)
257 return rinfo; // not local grid
258 }
259
260 rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName);
261 m_RegionInfoCache.Cache(scopeID, rinfo);
241 return rinfo; 262 return rinfo;
242 } 263 }
243 264
@@ -245,7 +266,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
245 { 266 {
246 List<GridRegion> rinfo = m_LocalGridService.GetRegionsByName(scopeID, name, maxNumber); 267 List<GridRegion> rinfo = m_LocalGridService.GetRegionsByName(scopeID, name, maxNumber);
247 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetRegionsByName {0} found {1} regions", name, rinfo.Count); 268 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetRegionsByName {0} found {1} regions", name, rinfo.Count);
248 List<GridRegion> grinfo = m_RemoteGridService.GetRegionsByName(scopeID, name, maxNumber); 269
270 // HG urls should not get here, strip them
271 // side effect is that local regions with same name as HG may also be found
272 // this mb good or bad
273 string regionName = name;
274 if(name.Contains("."))
275 {
276 if(string.IsNullOrWhiteSpace(m_ThisGatekeeper))
277 return rinfo; // no HG
278
279 string regionURI = "";
280 if(!Util.buildHGRegionURI(name, out regionURI, out regionName) || string.IsNullOrWhiteSpace(regionName))
281 return rinfo; // invalid
282 if(m_ThisGatekeeper != regionURI)
283 return rinfo; // not local grid
284 }
285
286 List<GridRegion> grinfo = m_RemoteGridService.GetRegionsByName(scopeID, regionName, maxNumber);
249 287
250 if (grinfo != null) 288 if (grinfo != null)
251 { 289 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index 25ae689..1378368 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
64 config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion"); 64 config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion");
65 config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion"); 65 config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion");
66 66
67 m_LocalConnector = new LocalGridServicesConnector(config); 67 m_LocalConnector = new LocalGridServicesConnector(config, null);
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
@@ -88,7 +88,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
88 Scene s = new Scene(new RegionInfo()); 88 Scene s = new Scene(new RegionInfo());
89 s.RegionInfo.RegionID = r1.RegionID; 89 s.RegionInfo.RegionID = r1.RegionID;
90 m_LocalConnector.AddRegion(s); 90 m_LocalConnector.AddRegion(s);
91 91
92 GridRegion r2 = new GridRegion(); 92 GridRegion r2 = new GridRegion();
93 r2.RegionName = "Test Region 2"; 93 r2.RegionName = "Test Region 2";
94 r2.RegionID = new UUID(2); 94 r2.RegionID = new UUID(2);
@@ -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/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 2238c90..1529fc2 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -37,7 +37,7 @@ using log4net;
37 37
38namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser 38namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
39{ 39{
40 public class ActivityDetector 40 public class ActivityDetector
41 { 41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 43
@@ -63,18 +63,31 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
63 scene.EventManager.OnNewClient -= OnNewClient; 63 scene.EventManager.OnNewClient -= OnNewClient;
64 } 64 }
65 65
66 public void OnMakeRootAgent(ScenePresence sp) 66 public void OnMakeRootAgent(ScenePresence sp)
67 { 67 {
68 if (sp.PresenceType != PresenceType.Npc) 68 if (sp.IsNPC)
69 return;
70
71 if(sp.gotCrossUpdate)
69 { 72 {
70 string userid; 73 Util.FireAndForget(delegate
71 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName);
72 if (sp.Scene.UserManagementModule.GetUserUUI(sp.UUID, out userid))
73 { 74 {
74 /* we only setposition on known agents that have a valid lookup */ 75 DoOnMakeRootAgent(sp);
75 m_GridUserService.SetLastPosition( 76 }, null, "ActivityDetector_MakeRoot");
76 userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 77 }
77 } 78 else
79 DoOnMakeRootAgent(sp);
80 }
81
82 public void DoOnMakeRootAgent(ScenePresence sp)
83 {
84 string userid;
85 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName);
86 if (sp.Scene.UserManagementModule.GetUserUUI(sp.UUID, out userid))
87 {
88 /* we only setposition on known agents that have a valid lookup */
89 m_GridUserService.SetLastPosition(
90 userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
78 } 91 }
79 } 92 }
80 93
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index 48f228a..7a4f981 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
86 } 86 }
87 } 87 }
88 88
89 public Type ReplaceableInterface 89 public Type ReplaceableInterface
90 { 90 {
91 get { return null; } 91 get { return null; }
92 } 92 }
@@ -203,21 +203,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
203 203
204 void OnClientClosed(UUID clientID, Scene scene) 204 void OnClientClosed(UUID clientID, Scene scene)
205 { 205 {
206 if (m_InventoryURLs.ContainsKey(clientID)) // if it's in cache 206 ScenePresence sp = null;
207 foreach (Scene s in m_Scenes)
207 { 208 {
208 ScenePresence sp = null; 209 s.TryGetScenePresence(clientID, out sp);
209 foreach (Scene s in m_Scenes) 210 if ((sp != null) && !sp.IsChildAgent && (s != scene))
210 { 211 {
211 s.TryGetScenePresence(clientID, out sp); 212 m_log.DebugFormat("[INVENTORY CACHE]: OnClientClosed in {0}, but user {1} still in sim. Keeping inventoryURL in cache",
212 if ((sp != null) && !sp.IsChildAgent && (s != scene))
213 {
214 m_log.DebugFormat("[INVENTORY CACHE]: OnClientClosed in {0}, but user {1} still in sim. Keeping inventoryURL in cache",
215 scene.RegionInfo.RegionName, clientID); 213 scene.RegionInfo.RegionName, clientID);
216 return; 214 return;
217 }
218 } 215 }
219 DropInventoryServiceURL(clientID);
220 } 216 }
217
218 if (m_InventoryURLs.ContainsKey(clientID)) // if it's in cache
219 DropInventoryServiceURL(clientID);
220
221 m_Cache.RemoveAll(clientID);
221 } 222 }
222 223
223 /// <summary> 224 /// <summary>
@@ -249,7 +250,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
249 if (inventoryURL != null && inventoryURL != string.Empty) 250 if (inventoryURL != null && inventoryURL != string.Empty)
250 { 251 {
251 inventoryURL = inventoryURL.Trim(new char[] { '/' }); 252 inventoryURL = inventoryURL.Trim(new char[] { '/' });
252 m_InventoryURLs[userID] = inventoryURL; 253 lock (m_InventoryURLs)
254 m_InventoryURLs[userID] = inventoryURL;
253 m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL); 255 m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL);
254 return; 256 return;
255 } 257 }
@@ -267,38 +269,45 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
267 if (!string.IsNullOrEmpty(inventoryURL)) 269 if (!string.IsNullOrEmpty(inventoryURL))
268 { 270 {
269 inventoryURL = inventoryURL.Trim(new char[] { '/' }); 271 inventoryURL = inventoryURL.Trim(new char[] { '/' });
270 m_InventoryURLs.Add(userID, inventoryURL); 272 lock (m_InventoryURLs)
273 m_InventoryURLs[userID] = inventoryURL;
271 m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL); 274 m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL);
272 } 275 }
273
274 } 276 }
275
276 } 277 }
277 } 278 }
278 279
279 private void DropInventoryServiceURL(UUID userID) 280 private void DropInventoryServiceURL(UUID userID)
280 { 281 {
281 lock (m_InventoryURLs) 282 lock (m_InventoryURLs)
283 {
282 if (m_InventoryURLs.ContainsKey(userID)) 284 if (m_InventoryURLs.ContainsKey(userID))
283 { 285 {
284 string url = m_InventoryURLs[userID]; 286 string url = m_InventoryURLs[userID];
285 m_InventoryURLs.Remove(userID); 287 m_InventoryURLs.Remove(userID);
286 m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Removed {0} from the cache of inventory URLs", url); 288 m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Removed {0} from the cache of inventory URLs", url);
287 } 289 }
290 }
288 } 291 }
289 292
290 public string GetInventoryServiceURL(UUID userID) 293 public string GetInventoryServiceURL(UUID userID)
291 { 294 {
292 if (m_InventoryURLs.ContainsKey(userID)) 295 lock (m_InventoryURLs)
293 return m_InventoryURLs[userID]; 296 {
297 if (m_InventoryURLs.ContainsKey(userID))
298 return m_InventoryURLs[userID];
299 }
294 300
295 CacheInventoryServiceURL(userID); 301 CacheInventoryServiceURL(userID);
296 302
297 if (m_InventoryURLs.ContainsKey(userID)) 303 lock (m_InventoryURLs)
298 return m_InventoryURLs[userID]; 304 {
305 if (m_InventoryURLs.ContainsKey(userID))
306 return m_InventoryURLs[userID];
307 }
299 308
300 return null; //it means that the methods should forward to local grid's inventory 309 return null; //it means that the methods should forward to local grid's inventory
301 310
302 } 311 }
303 #endregion 312 #endregion
304 313
@@ -598,21 +607,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
598 return connector.DeleteItems(ownerID, itemIDs); 607 return connector.DeleteItems(ownerID, itemIDs);
599 } 608 }
600 609
601 public InventoryItemBase GetItem(InventoryItemBase item) 610 public InventoryItemBase GetItem(UUID principalID, UUID itemID)
602 { 611 {
603 if (item == null)
604 return null;
605 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetItem " + item.ID); 612 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetItem " + item.ID);
606 613
607 string invURL = GetInventoryServiceURL(item.Owner); 614 string invURL = GetInventoryServiceURL(principalID);
608 615
609 if (invURL == null) // not there, forward to local inventory connector to resolve 616 if (invURL == null) // not there, forward to local inventory connector to resolve
610 lock (m_Lock) 617 lock (m_Lock)
611 return m_LocalGridInventoryService.GetItem(item); 618 return m_LocalGridInventoryService.GetItem(principalID, itemID);
612 619
613 IInventoryService connector = GetConnector(invURL); 620 IInventoryService connector = GetConnector(invURL);
614 621
615 return connector.GetItem(item); 622 return connector.GetItem(principalID, itemID);
616 } 623 }
617 624
618 public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs) 625 public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
@@ -632,22 +639,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
632 return connector.GetMultipleItems(userID, itemIDs); 639 return connector.GetMultipleItems(userID, itemIDs);
633 } 640 }
634 641
635 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 642 public InventoryFolderBase GetFolder(UUID principalID, UUID folderID)
636 { 643 {
637 if (folder == null)
638 return null;
639
640 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolder " + folder.ID); 644 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolder " + folder.ID);
641 645
642 string invURL = GetInventoryServiceURL(folder.Owner); 646 string invURL = GetInventoryServiceURL(principalID);
643 647
644 if (invURL == null) // not there, forward to local inventory connector to resolve 648 if (invURL == null) // not there, forward to local inventory connector to resolve
645 lock (m_Lock) 649 lock (m_Lock)
646 return m_LocalGridInventoryService.GetFolder(folder); 650 return m_LocalGridInventoryService.GetFolder(principalID, folderID);
647 651
648 IInventoryService connector = GetConnector(invURL); 652 IInventoryService connector = GetConnector(invURL);
649 653
650 return connector.GetFolder(folder); 654 return connector.GetFolder(principalID, folderID);
651 } 655 }
652 656
653 public bool HasInventoryForUser(UUID userID) 657 public bool HasInventoryForUser(UUID userID)
@@ -710,4 +714,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
710 return connector; 714 return connector;
711 } 715 }
712 } 716 }
713} \ No newline at end of file 717}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
index 3195e6b..f7ef2ea 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
@@ -38,12 +38,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
38 /// </summary> 38 /// </summary>
39 public class InventoryCache 39 public class InventoryCache
40 { 40 {
41 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour 41 private const double CACHE_EXPIRATION_SECONDS = 60.0; // 1 minute
42 42
43 private static ExpiringCache<UUID, InventoryFolderBase> m_RootFolders = new ExpiringCache<UUID, InventoryFolderBase>(); 43 private static ExpiringCache<UUID, InventoryFolderBase> m_RootFolders = new ExpiringCache<UUID, InventoryFolderBase>();
44 private static ExpiringCache<UUID, Dictionary<FolderType, InventoryFolderBase>> m_FolderTypes = new ExpiringCache<UUID, Dictionary<FolderType, InventoryFolderBase>>(); 44 private static ExpiringCache<UUID, Dictionary<FolderType, InventoryFolderBase>> m_FolderTypes = new ExpiringCache<UUID, Dictionary<FolderType, InventoryFolderBase>>();
45 private static ExpiringCache<UUID, InventoryCollection> m_Inventories = new ExpiringCache<UUID, InventoryCollection>(); 45 private static ExpiringCache<UUID, InventoryCollection> m_Inventories = new ExpiringCache<UUID, InventoryCollection>();
46 46
47
48 public void RemoveAll(UUID userID)
49 {
50 if(m_RootFolders.Contains(userID))
51 m_RootFolders.Remove(userID);
52 if(m_FolderTypes.Contains(userID))
53 m_FolderTypes.Remove(userID);
54 if(m_Inventories.Contains(userID))
55 m_Inventories.Remove(userID);
56 }
57
47 public void Cache(UUID userID, InventoryFolderBase root) 58 public void Cache(UUID userID, InventoryFolderBase root)
48 { 59 {
49 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS); 60 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index 20d4e02..fa36b66 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
72 72
73 private bool m_Enabled = false; 73 private bool m_Enabled = false;
74 74
75 public Type ReplaceableInterface 75 public Type ReplaceableInterface
76 { 76 {
77 get { return null; } 77 get { return null; }
78 } 78 }
@@ -134,7 +134,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
134 { 134 {
135 if (!m_Enabled) 135 if (!m_Enabled)
136 return; 136 return;
137 137
138 scene.RegisterModuleInterface<IInventoryService>(this); 138 scene.RegisterModuleInterface<IInventoryService>(this);
139 139
140 if (Scene == null) 140 if (Scene == null)
@@ -261,9 +261,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
261 public bool AddItem(InventoryItemBase item) 261 public bool AddItem(InventoryItemBase item)
262 { 262 {
263// m_log.DebugFormat( 263// m_log.DebugFormat(
264// "[LOCAL INVENTORY SERVICES CONNECTOR]: Adding inventory item {0} to user {1} folder {2}", 264// "[LOCAL INVENTORY SERVICES CONNECTOR]: Adding inventory item {0} to user {1} folder {2}",
265// item.Name, item.Owner, item.Folder); 265// item.Name, item.Owner, item.Folder);
266 266
267 return m_InventoryService.AddItem(item); 267 return m_InventoryService.AddItem(item);
268 } 268 }
269 269
@@ -292,13 +292,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
292 return m_InventoryService.DeleteItems(ownerID, itemIDs); 292 return m_InventoryService.DeleteItems(ownerID, itemIDs);
293 } 293 }
294 294
295 public InventoryItemBase GetItem(InventoryItemBase item) 295 public InventoryItemBase GetItem(UUID principalID, UUID itemID)
296 { 296 {
297// m_log.DebugFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Requesting inventory item {0}", item.ID); 297// m_log.DebugFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Requesting inventory item {0}", item.ID);
298 298
299// UUID requestedItemId = item.ID; 299// UUID requestedItemId = item.ID;
300 300
301 item = m_InventoryService.GetItem(item); 301 InventoryItemBase item = m_InventoryService.GetItem(principalID, itemID);
302 302
303// if (null == item) 303// if (null == item)
304// m_log.ErrorFormat( 304// m_log.ErrorFormat(
@@ -312,9 +312,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
312 return m_InventoryService.GetMultipleItems(userID, itemIDs); 312 return m_InventoryService.GetMultipleItems(userID, itemIDs);
313 } 313 }
314 314
315 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 315 public InventoryFolderBase GetFolder(UUID principalID, UUID folderID)
316 { 316 {
317 return m_InventoryService.GetFolder(folder); 317 return m_InventoryService.GetFolder(principalID, folderID);
318 } 318 }
319 319
320 /// <summary> 320 /// <summary>
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 978b9d9..d8ae2c4 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -74,7 +74,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
74 } 74 }
75 } 75 }
76 76
77 public Type ReplaceableInterface 77 public Type ReplaceableInterface
78 { 78 {
79 get { return null; } 79 get { return null; }
80 } 80 }
@@ -292,15 +292,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
292 return m_RemoteConnector.DeleteItems(ownerID, itemIDs); 292 return m_RemoteConnector.DeleteItems(ownerID, itemIDs);
293 } 293 }
294 294
295 public InventoryItemBase GetItem(InventoryItemBase item) 295 public InventoryItemBase GetItem(UUID userID, UUID itemID)
296 { 296 {
297 //m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetItem {0}", item.ID); 297 //m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetItem {0}", item.ID);
298 if (item == null)
299 return null;
300 298
301 if (m_RemoteConnector == null) 299 if (m_RemoteConnector == null)
302 m_log.DebugFormat("[XINVENTORY CONNECTOR]: connector stub is null!!!"); 300 m_log.DebugFormat("[XINVENTORY CONNECTOR]: connector stub is null!!!");
303 return m_RemoteConnector.GetItem(item); 301 return m_RemoteConnector.GetItem(userID, itemID);
304 } 302 }
305 303
306 public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs) 304 public InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] itemIDs)
@@ -311,13 +309,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
311 return m_RemoteConnector.GetMultipleItems(userID, itemIDs); 309 return m_RemoteConnector.GetMultipleItems(userID, itemIDs);
312 } 310 }
313 311
314 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 312 public InventoryFolderBase GetFolder(UUID userID, UUID folderID)
315 { 313 {
316 //m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetFolder {0}", folder.ID); 314 //m_log.DebugFormat("[XINVENTORY CONNECTOR]: GetFolder {0}", folder.ID);
317 if (folder == null)
318 return null;
319 315
320 return m_RemoteConnector.GetFolder(folder); 316 return m_RemoteConnector.GetFolder(userID, folderID);
321 } 317 }
322 318
323 public bool HasInventoryForUser(UUID userID) 319 public bool HasInventoryForUser(UUID userID)
@@ -337,4 +333,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
337 333
338 #endregion 334 #endregion
339 } 335 }
340} \ No newline at end of file 336}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs
index 5329933..8baf41a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs
@@ -62,7 +62,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land
62 62
63 #region ISharedRegionModule 63 #region ISharedRegionModule
64 64
65 public Type ReplaceableInterface 65 public Type ReplaceableInterface
66 { 66 {
67 get { return null; } 67 get { return null; }
68 } 68 }
@@ -121,15 +121,32 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land
121 public LandData GetLandData(UUID scopeID, ulong regionHandle, uint x, uint y, out byte regionAccess) 121 public LandData GetLandData(UUID scopeID, ulong regionHandle, uint x, uint y, out byte regionAccess)
122 { 122 {
123 regionAccess = 2; 123 regionAccess = 2;
124 m_log.DebugFormat("[LAND CONNECTOR]: request for land data in {0} at {1}, {2}", 124// m_log.DebugFormat("[LAND CONNECTOR]: request for land data in {0} at {1}, {2}",
125 regionHandle, x, y); 125// regionHandle, x, y);
126
127 uint rx = 0, ry = 0;
128 Util.RegionHandleToWorldLoc(regionHandle, out rx, out ry);
126 129
127 foreach (Scene s in m_Scenes) 130 foreach (Scene s in m_Scenes)
128 { 131 {
129 if (s.RegionInfo.RegionHandle == regionHandle) 132 uint t = s.RegionInfo.WorldLocX;
133 if( rx < t)
134 continue;
135 t += s.RegionInfo.RegionSizeX;
136 if( rx >= t)
137 continue;
138 t = s.RegionInfo.WorldLocY;
139 if( ry < t)
140 continue;
141 t += s.RegionInfo.RegionSizeY;
142 if( ry < t)
130 { 143 {
131 LandData land = s.GetLandData(x, y); 144 LandData land = s.GetLandData(x, y);
132 regionAccess = s.RegionInfo.AccessLevel; 145 regionAccess = s.RegionInfo.AccessLevel;
146 IDwellModule dwellModule = s.RequestModuleInterface<IDwellModule>();
147 if (dwellModule != null)
148 land.Dwell = dwellModule.GetDwell(land);
149
133 return land; 150 return land;
134 } 151 }
135 } 152 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs
index 77dfa4a..68c5b64 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land
53 private bool m_Enabled = false; 53 private bool m_Enabled = false;
54 private LocalLandServicesConnector m_LocalService; 54 private LocalLandServicesConnector m_LocalService;
55 55
56 public Type ReplaceableInterface 56 public Type ReplaceableInterface
57 { 57 {
58 get { return null; } 58 get { return null; }
59 } 59 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 08d6bdd..9888c3b 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 =
@@ -67,11 +68,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
67 private int m_refreshtime = 0; 68 private int m_refreshtime = 0;
68 private int m_lastrefresh = 0; 69 private int m_lastrefresh = 0;
69 private System.Timers.Timer m_refreshTimer; 70 private System.Timers.Timer m_refreshTimer;
70 71
71 #region ISharedRegionModule 72 #region ISharedRegionModule
72 73
73 public Type ReplaceableInterface { get { return null; } } 74 public Type ReplaceableInterface { get { return null; } }
74 public string Name { get { return "MapImageServiceModule"; } } 75 public string Name { get { return "MapImageServiceModule"; } }
75 public void RegionLoaded(Scene scene) { } 76 public void RegionLoaded(Scene scene) { }
76 public void Close() { } 77 public void Close() { }
77 public void PostInitialise() { } 78 public void PostInitialise() { }
@@ -94,8 +95,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
94 return; 95 return;
95 96
96 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); 97 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime"));
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.");
@@ -116,22 +115,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
116 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Unable to load LocalServiceModule from {0}. MapService module disabled. Please fix the configuration.", service); 115 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Unable to load LocalServiceModule from {0}. MapService module disabled. Please fix the configuration.", service);
117 return; 116 return;
118 } 117 }
119 118
120 // we don't want the timer if the interval is zero, but we still want this module enables 119 // we don't want the timer if the interval is zero, but we still want this module enables
121 if(refreshminutes > 0) 120 if(refreshminutes > 0)
122 { 121 {
123 m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms 122 m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms
124 123
125 m_refreshTimer = new System.Timers.Timer(); 124 m_refreshTimer = new System.Timers.Timer();
126 m_refreshTimer.Enabled = true; 125 m_refreshTimer.Enabled = true;
127 m_refreshTimer.AutoReset = true; 126 m_refreshTimer.AutoReset = true;
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 }
134 else 134 else
135 { 135 {
136 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with no refresh and service object {0}", service); 136 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with no refresh and service object {0}", service);
137 } 137 }
@@ -171,7 +171,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
171 } 171 }
172 172
173 #endregion ISharedRegionModule 173 #endregion ISharedRegionModule
174 174
175 ///<summary> 175 ///<summary>
176 /// 176 ///
177 ///</summary> 177 ///</summary>
@@ -210,7 +210,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
210 return; 210 return;
211 } 211 }
212 212
213 m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.Name);
214 213
215 // mapTile.Save( // DEBUG DEBUG 214 // mapTile.Save( // DEBUG DEBUG
216 // String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY), 215 // String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY),
@@ -218,12 +217,17 @@ 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 217 // 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) 218 if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
220 { 219 {
221 ConvertAndUploadMaptile(mapTile, 220 m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.Name);
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 }
225 else 225 else
226 { 226 {
227 m_log.DebugFormat("{0} Upload {1} maptiles for {2}", LogHeader,
228 (mapTile.Width * mapTile.Height) / (Constants.RegionSize * Constants.RegionSize),
229 scene.Name);
230
227 // For larger regions (varregion) we must cut the region image into legacy sized 231 // For larger regions (varregion) we must cut the region image into legacy sized
228 // pieces since that is how the maptile system works. 232 // pieces since that is how the maptile system works.
229 // Note the assumption that varregions are always a multiple of legacy size. 233 // Note the assumption that varregions are always a multiple of legacy size.
@@ -240,7 +244,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
240 (int)Constants.RegionSize, (int)Constants.RegionSize); 244 (int)Constants.RegionSize, (int)Constants.RegionSize);
241 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat)) 245 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
242 { 246 {
243 ConvertAndUploadMaptile(subMapTile, 247 ConvertAndUploadMaptile(scene, subMapTile,
244 scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize), 248 scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize),
245 scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize), 249 scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize),
246 scene.Name); 250 scene.Name);
@@ -253,8 +257,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
253 ///<summary> 257 ///<summary>
254 /// 258 ///
255 ///</summary> 259 ///</summary>
256 private void UploadMapTile(IScene scene) 260 public void UploadMapTile(IScene scene)
257 { 261 {
262 m_log.DebugFormat("{0}: upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName);
263
258 // Create a JPG map tile and upload it to the AddMapTile API 264 // Create a JPG map tile and upload it to the AddMapTile API
259 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>(); 265 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
260 if (tileGenerator == null) 266 if (tileGenerator == null)
@@ -265,18 +271,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
265 271
266 using (Bitmap mapTile = tileGenerator.CreateMapTile()) 272 using (Bitmap mapTile = tileGenerator.CreateMapTile())
267 { 273 {
268 if (mapTile != null) 274 // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
269 { 275 // is no static map tile.
270 UploadMapTile(scene, mapTile); 276 if (mapTile == null)
271 } 277 return;
272 else 278
273 { 279 UploadMapTile(scene, mapTile);
274 m_log.WarnFormat("{0} Tile image generation failed", LogHeader);
275 }
276 } 280 }
277 } 281 }
278 282
279 private void ConvertAndUploadMaptile(Image tileImage, uint locX, uint locY, string regionName) 283 private void ConvertAndUploadMaptile(IScene scene, Image tileImage, uint locX, uint locY, string regionName)
280 { 284 {
281 byte[] jpgData = Utils.EmptyBytes; 285 byte[] jpgData = Utils.EmptyBytes;
282 286
@@ -288,7 +292,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
288 if (jpgData != Utils.EmptyBytes) 292 if (jpgData != Utils.EmptyBytes)
289 { 293 {
290 string reason = string.Empty; 294 string reason = string.Empty;
291 if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, out reason)) 295 if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, scene.RegionInfo.ScopeID, out reason))
292 { 296 {
293 m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader, 297 m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
294 regionName, locX, locY, reason); 298 regionName, locX, locY, reason);
@@ -300,4 +304,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
300 } 304 }
301 } 305 }
302 } 306 }
303} \ No newline at end of file 307}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MuteList/LocalMuteListServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MuteList/LocalMuteListServiceConnector.cs
new file mode 100644
index 0000000..37b30aa
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MuteList/LocalMuteListServiceConnector.cs
@@ -0,0 +1,188 @@
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 log4net;
29using Mono.Addins;
30using Nini.Config;
31using System;
32using System.Collections.Generic;
33using System.Reflection;
34using OpenSim.Framework;
35using OpenSim.Server.Base;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
39using OpenMetaverse;
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MuteList
42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalMuteListServicesConnector")]
44 public class LocalMuteListServicesConnector : ISharedRegionModule, IMuteListService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private List<Scene> m_Scenes = new List<Scene>();
51 protected IMuteListService m_service = null;
52
53 private bool m_Enabled = false;
54
55 #region ISharedRegionModule
56
57 public Type ReplaceableInterface
58 {
59 get { return null; }
60 }
61
62 public string Name
63 {
64 get { return "LocalMuteListServicesConnector"; }
65 }
66
67 public void Initialise(IConfigSource source)
68 {
69 // only active for core mute lists module
70 IConfig moduleConfig = source.Configs["Messaging"];
71 if (moduleConfig == null)
72 return;
73
74 if (moduleConfig.GetString("MuteListModule", "None") != "MuteListModuleTst")
75 return;
76
77 moduleConfig = source.Configs["Modules"];
78
79 if (moduleConfig == null)
80 return;
81
82 string name = moduleConfig.GetString("MuteListService", "");
83 if(name != Name)
84 return;
85
86 IConfig userConfig = source.Configs["MuteListService"];
87 if (userConfig == null)
88 {
89 m_log.Error("[MuteList LOCALCONNECTOR]: MuteListService missing from configuration");
90 return;
91 }
92
93 string serviceDll = userConfig.GetString("LocalServiceModule",
94 String.Empty);
95
96 if (serviceDll == String.Empty)
97 {
98 m_log.Error("[MuteList LOCALCONNECTOR]: No LocalServiceModule named in section MuteListService");
99 return;
100 }
101
102 Object[] args = new Object[] { source };
103 try
104 {
105 m_service = ServerUtils.LoadPlugin<IMuteListService>(serviceDll, args);
106 }
107 catch
108 {
109 m_log.Error("[MuteList LOCALCONNECTOR]: Failed to load mute service");
110 return;
111 }
112
113 if (m_service == null)
114 {
115 m_log.Error("[MuteList LOCALCONNECTOR]: Can't load MuteList service");
116 return;
117 }
118
119 m_Enabled = true;
120 m_log.Info("[MuteList LOCALCONNECTOR]: enabled");
121 }
122
123 public void Close()
124 {
125 }
126
127 public void AddRegion(Scene scene)
128 {
129 if (!m_Enabled)
130 return;
131
132 lock(m_Scenes)
133 {
134 m_Scenes.Add(scene);
135 scene.RegisterModuleInterface<IMuteListService>(this);
136 }
137 }
138
139 public void RegionLoaded(Scene scene)
140 {
141 }
142
143 public void PostInitialise()
144 {
145 }
146
147 public void RemoveRegion(Scene scene)
148 {
149 if (!m_Enabled)
150 return;
151
152 lock(m_Scenes)
153 {
154 if (m_Scenes.Contains(scene))
155 {
156 m_Scenes.Remove(scene);
157 scene.UnregisterModuleInterface<IMuteListService>(this);
158 }
159 }
160 }
161
162 #endregion ISharedRegionModule
163
164 #region IMuteListService
165 public Byte[] MuteListRequest(UUID agentID, uint crc)
166 {
167 if (!m_Enabled)
168 return null;
169 return m_service.MuteListRequest(agentID, crc);
170 }
171
172 public bool UpdateMute(MuteData mute)
173 {
174 if (!m_Enabled)
175 return false;
176 return m_service.UpdateMute(mute);
177 }
178
179 public bool RemoveMute(UUID agentID, UUID muteID, string muteName)
180 {
181 if (!m_Enabled)
182 return false;
183 return m_service.RemoveMute(agentID, muteID, muteName);
184 }
185
186 #endregion IMuteListService
187 }
188}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetDisplayNamesModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MuteList/RemoteMuteListServiceConnector.cs
index 6617bbc..a5dec64 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetDisplayNamesModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MuteList/RemoteMuteListServiceConnector.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -24,121 +24,120 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
28using System; 27using System;
29using System.Collections; 28using System.Collections.Generic;
30using System.Collections.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.Reflection; 29using System.Reflection;
34using System.IO;
35using System.Web;
36using log4net;
37using Nini.Config;
38using Mono.Addins;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenMetaverse.Imaging;
42using OpenSim.Framework; 30using OpenSim.Framework;
43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.Framework.Interfaces; 31using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Server.Base;
47using OpenSim.Services.Interfaces; 34using OpenSim.Services.Interfaces;
48using Caps = OpenSim.Framework.Capabilities.Caps; 35using OpenSim.Services.Connectors;
49using OpenSim.Capabilities.Handlers;
50 36
51namespace OpenSim.Region.ClientStack.Linden 37using OpenMetaverse;
52{ 38using log4net;
39using Mono.Addins;
40using Nini.Config;
53 41
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetDisplayNamesModule")] 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MuteList
55 public class GetDisplayNamesModule : INonSharedRegionModule 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteMuteListServicesConnector")]
45 public class RemoteMuteListServicesConnector : ISharedRegionModule, IMuteListService
56 { 46 {
57 private static readonly ILog m_log = 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48
59 49 #region ISharedRegionModule
60 private Scene m_scene;
61 private IUserManagement m_UserManager;
62 50
63 private bool m_Enabled = false; 51 private bool m_Enabled = false;
64 52
65 private string m_URL; 53 private IMuteListService m_remoteConnector;
66 54
67 #region ISharedRegionModule Members 55 public Type ReplaceableInterface
56 {
57 get { return null; }
58 }
59
60 public string Name
61 {
62 get { return "RemoteMuteListServicesConnector"; }
63 }
68 64
69 public void Initialise(IConfigSource source) 65 public void Initialise(IConfigSource source)
70 { 66 {
71 IConfig config = source.Configs["ClientStack.LindenCaps"]; 67 // only active for core mute lists module
72 if (config == null) 68 IConfig moduleConfig = source.Configs["Messaging"];
69 if (moduleConfig == null)
73 return; 70 return;
74 71
75 m_URL = config.GetString("Cap_GetDisplayNames", string.Empty); 72 if (moduleConfig.GetString("MuteListModule", "None") != "MuteListModuleTst")
76 if (m_URL != string.Empty) 73 return;
77 m_Enabled = true; 74
75 moduleConfig = source.Configs["Modules"];
76 if (moduleConfig != null)
77 {
78 string name = moduleConfig.GetString("MuteListService", "");
79 if (name == Name)
80 {
81 m_remoteConnector = new MuteListServicesConnector(source);
82 m_Enabled = true;
83 }
84 }
78 } 85 }
79 86
80 public void AddRegion(Scene s) 87 public void PostInitialise()
81 { 88 {
82 if (!m_Enabled) 89 }
83 return;
84 90
85 m_scene = s; 91 public void Close()
92 {
86 } 93 }
87 94
88 public void RemoveRegion(Scene s) 95 public void AddRegion(Scene scene)
89 { 96 {
90 if (!m_Enabled) 97 if (!m_Enabled)
91 return; 98 return;
92 99
93 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 100 scene.RegisterModuleInterface<IMuteListService>(this);
94 m_scene = null; 101 m_log.InfoFormat("[MUTELIST CONNECTOR]: Enabled for region {0}", scene.RegionInfo.RegionName);
95 } 102 }
96 103
97 public void RegionLoaded(Scene s) 104 public void RemoveRegion(Scene scene)
98 { 105 {
99 if (!m_Enabled) 106 if (!m_Enabled)
100 return; 107 return;
101
102 m_UserManager = m_scene.RequestModuleInterface<IUserManagement>();
103 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
104 } 108 }
105 109
106 public void PostInitialise() 110 public void RegionLoaded(Scene scene)
107 { 111 {
112 if (!m_Enabled)
113 return;
108 } 114 }
109 115
110 public void Close() { } 116 #endregion
111
112 public string Name { get { return "GetDisplayNamesModule"; } }
113 117
114 public Type ReplaceableInterface 118 #region IMuteListService
119 public Byte[] MuteListRequest(UUID agentID, uint crc)
115 { 120 {
116 get { return null; } 121 if (!m_Enabled)
122 return null;
123 return m_remoteConnector.MuteListRequest(agentID, crc);
117 } 124 }
118 125
119 #endregion 126 public bool UpdateMute(MuteData mute)
120
121 public void RegisterCaps(UUID agentID, Caps caps)
122 { 127 {
123 UUID capID = UUID.Random(); 128 if (!m_Enabled)
129 return false;
130 return m_remoteConnector.UpdateMute(mute);
131 }
124 132
125 if (m_URL == "localhost") 133 public bool RemoveMute(UUID agentID, UUID muteID, string muteName)
126 { 134 {
127 m_log.DebugFormat("[GET_DISPLAY_NAMES]: /CAPS/agents/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 135 if (!m_Enabled)
128 caps.RegisterHandler( 136 return false;
129 "GetDisplayNames", 137 return m_remoteConnector.RemoveMute(agentID, muteID, muteName);
130 new GetDisplayNamesHandler("/CAPS/agents" + capID + "/", m_UserManager, "GetDisplayNames", agentID.ToString()));
131 }
132 else
133 {
134// m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName);
135 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
136 if (handler != null)
137 handler.RegisterExternalUserCapsHandler(agentID,caps,"GetDisplayNames", m_URL);
138 else
139 caps.RegisterHandler("GetDisplayNames", m_URL);
140 }
141 } 138 }
142 139
140 #endregion IMuteListService
141
143 } 142 }
144} 143}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/NeighbourServiceOutConnector.cs
index bda354f..60addec 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/NeighbourServiceOutConnector.cs
@@ -25,52 +25,40 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net; 28using log4net;
32using Mono.Addins; 29using Mono.Addins;
30using System;
31using System.Reflection;
32using System.Collections.Generic;
33using Nini.Config; 33using Nini.Config;
34using OpenMetaverse;
35using OpenSim.Framework; 34using OpenSim.Framework;
36using OpenSim.Server.Base; 35using OpenSim.Services.Connectors;
37using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
40 39
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalNeighbourServicesConnector")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "NeighbourServicesOutConnector")]
44 public class LocalNeighbourServicesConnector : 44 public class NeighbourServicesOutConnector :
45 ISharedRegionModule, INeighbourService 45 NeighbourServicesConnector, ISharedRegionModule, INeighbourService
46 { 46 {
47 private static readonly ILog m_log = 47 private static readonly ILog m_log =
48 LogManager.GetLogger( 48 LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType); 49 MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private List<Scene> m_Scenes = new List<Scene>(); 51 private List<Scene> m_Scenes = new List<Scene>();
52
53 private bool m_Enabled = false; 52 private bool m_Enabled = false;
54 53
55 public LocalNeighbourServicesConnector() 54 public Type ReplaceableInterface
56 {
57 }
58
59 public LocalNeighbourServicesConnector(List<Scene> scenes)
60 {
61 m_Scenes = scenes;
62 }
63
64 #region ISharedRegionModule
65
66 public Type ReplaceableInterface
67 { 55 {
68 get { return null; } 56 get { return null; }
69 } 57 }
70 58
71 public string Name 59 public string Name
72 { 60 {
73 get { return "LocalNeighbourServicesConnector"; } 61 get { return "NeighbourServicesOutConnector"; }
74 } 62 }
75 63
76 public void Initialise(IConfigSource source) 64 public void Initialise(IConfigSource source)
@@ -78,68 +66,69 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
78 IConfig moduleConfig = source.Configs["Modules"]; 66 IConfig moduleConfig = source.Configs["Modules"];
79 if (moduleConfig != null) 67 if (moduleConfig != null)
80 { 68 {
81 string name = moduleConfig.GetString("NeighbourServices", this.Name); 69 string name = moduleConfig.GetString("NeighbourServices");
82 if (name == Name) 70 if (name == Name)
83 { 71 {
84 // m_Enabled rules whether this module registers as INeighbourService or not
85 m_Enabled = true; 72 m_Enabled = true;
86 m_log.Info("[NEIGHBOUR CONNECTOR]: Local neighbour connector enabled"); 73 m_log.Info("[NEIGHBOUR CONNECTOR]: Neighbour out connector enabled");
87 } 74 }
88 } 75 }
89 } 76 }
90 77
78 public void PostInitialise()
79 {
80 }
81
91 public void Close() 82 public void Close()
92 { 83 {
93 } 84 }
94 85
95 public void AddRegion(Scene scene) 86 public void AddRegion(Scene scene)
96 { 87 {
97 m_Scenes.Add(scene);
98
99 if (!m_Enabled) 88 if (!m_Enabled)
100 return; 89 return;
101 90
91 m_Scenes.Add(scene);
102 scene.RegisterModuleInterface<INeighbourService>(this); 92 scene.RegisterModuleInterface<INeighbourService>(this);
103 } 93 }
104 94
105 public void RegionLoaded(Scene scene)
106 {
107 m_log.Info("[NEIGHBOUR CONNECTOR]: Local neighbour connector enabled for region " + scene.RegionInfo.RegionName);
108 }
109
110 public void PostInitialise()
111 {
112 }
113
114 public void RemoveRegion(Scene scene) 95 public void RemoveRegion(Scene scene)
115 { 96 {
116 // Always remove 97 // Always remove
117 if (m_Scenes.Contains(scene)) 98 if (m_Scenes.Contains(scene))
118 m_Scenes.Remove(scene); 99 m_Scenes.Remove(scene);
119 } 100 }
120 101
121 #endregion ISharedRegionModule 102 public void RegionLoaded(Scene scene)
103 {
104 if (!m_Enabled)
105 return;
106
107 m_GridService = scene.GridService;
108 m_log.InfoFormat("[NEIGHBOUR CONNECTOR]: Enabled out neighbours for region {0}", scene.RegionInfo.RegionName);
109
110 }
122 111
123 #region INeighbourService 112 #region INeighbourService
124 113
125 public OpenSim.Services.Interfaces.GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion) 114 public override GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion)
126 { 115 {
127 uint x, y; 116 if (!m_Enabled)
128 Util.RegionHandleToRegionLoc(regionHandle, out x, out y); 117 return null;
129 118
130 foreach (Scene s in m_Scenes) 119 foreach (Scene s in m_Scenes)
131 { 120 {
132 if (s.RegionInfo.RegionHandle == regionHandle) 121 if (s.RegionInfo.RegionHandle == regionHandle)
133 { 122 {
134 m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}", 123// uint x, y;
135 thisRegion.RegionName, s.Name, x, y ); 124// Util.RegionHandleToRegionLoc(regionHandle, out x, out y);
136 125// m_log.DebugFormat("[NEIGHBOUR SERVICE OUT CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
137 //m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour"); 126// thisRegion.RegionName, s.Name, x, y );
138 return s.IncomingHelloNeighbour(thisRegion); 127 return s.IncomingHelloNeighbour(thisRegion);
139 } 128 }
140 } 129 }
141 //m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: region handle {0} not found", regionHandle); 130
142 return null; 131 return base.HelloNeighbour(regionHandle, thisRegion);
143 } 132 }
144 133
145 #endregion INeighbourService 134 #endregion INeighbourService
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs
deleted file mode 100644
index e6772f3..0000000
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs
+++ /dev/null
@@ -1,157 +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 log4net;
29using Mono.Addins;
30using System;
31using System.Collections.Generic;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Services.Connectors;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
39using OpenSim.Server.Base;
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteNeighbourServicesConnector")]
44 public class RemoteNeighbourServicesConnector :
45 NeighbourServicesConnector, ISharedRegionModule, INeighbourService
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType);
50
51 private bool m_Enabled = false;
52 private LocalNeighbourServicesConnector m_LocalService;
53 //private string serviceDll;
54 //private List<Scene> m_Scenes = new List<Scene>();
55
56 public Type ReplaceableInterface
57 {
58 get { return null; }
59 }
60
61 public string Name
62 {
63 get { return "RemoteNeighbourServicesConnector"; }
64 }
65
66 public void Initialise(IConfigSource source)
67 {
68 IConfig moduleConfig = source.Configs["Modules"];
69 if (moduleConfig != null)
70 {
71 string name = moduleConfig.GetString("NeighbourServices");
72 if (name == Name)
73 {
74 m_LocalService = new LocalNeighbourServicesConnector();
75
76 //IConfig neighbourConfig = source.Configs["NeighbourService"];
77 //if (neighbourConfig == null)
78 //{
79 // m_log.Error("[NEIGHBOUR CONNECTOR]: NeighbourService missing from OpenSim.ini");
80 // return;
81 //}
82 //serviceDll = neighbourConfig.GetString("LocalServiceModule", String.Empty);
83 //if (serviceDll == String.Empty)
84 //{
85 // m_log.Error("[NEIGHBOUR CONNECTOR]: No LocalServiceModule named in section NeighbourService");
86 // return;
87 //}
88
89 m_Enabled = true;
90
91 m_log.Info("[NEIGHBOUR CONNECTOR]: Remote Neighbour connector enabled");
92 }
93 }
94 }
95
96 public void PostInitialise()
97 {
98 //if (m_Enabled)
99 //{
100 // Object[] args = new Object[] { m_Scenes };
101 // m_LocalService =
102 // ServerUtils.LoadPlugin<INeighbourService>(serviceDll,
103 // args);
104
105 // if (m_LocalService == null)
106 // {
107 // m_log.Error("[NEIGHBOUR CONNECTOR]: Can't load neighbour service");
108 // Unregister();
109 // return;
110 // }
111 //}
112 }
113
114 public void Close()
115 {
116 }
117
118 public void AddRegion(Scene scene)
119 {
120 if (!m_Enabled)
121 return;
122
123 m_LocalService.AddRegion(scene);
124 scene.RegisterModuleInterface<INeighbourService>(this);
125 }
126
127 public void RemoveRegion(Scene scene)
128 {
129 if (m_Enabled)
130 m_LocalService.RemoveRegion(scene);
131 }
132
133 public void RegionLoaded(Scene scene)
134 {
135 if (!m_Enabled)
136 return;
137
138 m_GridService = scene.GridService;
139
140 m_log.InfoFormat("[NEIGHBOUR CONNECTOR]: Enabled remote neighbours for region {0}", scene.RegionInfo.RegionName);
141
142 }
143
144 #region INeighbourService
145
146 public override GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion)
147 {
148 GridRegion region = m_LocalService.HelloNeighbour(regionHandle, thisRegion);
149 if (region != null)
150 return region;
151
152 return base.HelloNeighbour(regionHandle, thisRegion);
153 }
154
155 #endregion INeighbourService
156 }
157}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
index fdbe10a..e014a57 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
@@ -123,6 +123,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
123 return m_PresenceService.GetAgent(sessionID); 123 return m_PresenceService.GetAgent(sessionID);
124 } 124 }
125 125
126 public PresenceInfo GetAgentByUser(UUID userID)
127 {
128 return m_PresenceService.GetAgentByUser(userID);
129 }
130
126 public PresenceInfo[] GetAgents(string[] userIDs) 131 public PresenceInfo[] GetAgents(string[] userIDs)
127 { 132 {
128 // Don't bother potentially making a useless network call if we not going to ask for any users anyway. 133 // Don't bother potentially making a useless network call if we not going to ask for any users anyway.
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
index 50c252c..a7e62eb 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
@@ -35,7 +35,7 @@ using OpenSim.Services.Interfaces;
35 35
36namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence 36namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
37{ 37{
38 public class PresenceDetector 38 public class PresenceDetector
39 { 39 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 41
@@ -68,6 +68,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
68 68
69 public void OnMakeRootAgent(ScenePresence sp) 69 public void OnMakeRootAgent(ScenePresence sp)
70 { 70 {
71 if (sp.IsNPC)
72 return;
73
74 if(sp.gotCrossUpdate)
75 {
76 Util.FireAndForget(delegate
77 {
78 DoOnMakeRootAgent(sp);
79 }, null, "PresenceDetector_MakeRoot");
80 }
81 else
82 DoOnMakeRootAgent(sp);
83 }
84
85 public void DoOnMakeRootAgent(ScenePresence sp)
86 {
71// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); 87// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
72 if (sp.PresenceType != PresenceType.Npc) 88 if (sp.PresenceType != PresenceType.Npc)
73 m_PresenceService.ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID); 89 m_PresenceService.ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
index 69bac82..7838d12 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
72 public void TestPresenceV0_1() 72 public void TestPresenceV0_1()
73 { 73 {
74 SetUp(); 74 SetUp();
75 75
76 // Let's stick in a test presence 76 // Let's stick in a test presence
77 /* 77 /*
78 PresenceData p = new PresenceData(); 78 PresenceData p = new PresenceData();
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index cc8203e..57aba05 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;
@@ -219,7 +219,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
219 } 219 }
220 220
221// m_log.DebugFormat( 221// m_log.DebugFormat(
222// "[LOCAL COMMS]: Did not find region {0} {1} for ChildAgentUpdate", 222// "[LOCAL COMMS]: Did not find region {0} {1} for ChildAgentUpdate",
223// destination.RegionName, destination.RegionID); 223// destination.RegionName, destination.RegionID);
224 224
225 return false; 225 return false;
@@ -265,9 +265,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
265 reason = "Destination is a variable-sized region, and source is an old simulator. Consider upgrading."; 265 reason = "Destination is a variable-sized region, and source is an old simulator. Consider upgrading.";
266 m_log.DebugFormat("[LOCAL SIMULATION CONNECTOR]: Request to access this variable-sized region from older simulator was denied"); 266 m_log.DebugFormat("[LOCAL SIMULATION CONNECTOR]: Request to access this variable-sized region from older simulator was denied");
267 return false; 267 return false;
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..b402d2a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -137,7 +137,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
137 } 137 }
138 138
139 protected virtual void InitOnce(Scene scene) 139 protected virtual void InitOnce(Scene scene)
140 { 140 {
141 m_aScene = scene; 141 m_aScene = scene;
142 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService); 142 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
143 } 143 }
@@ -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)
@@ -249,7 +248,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
249 // else do the remote thing 248 // else do the remote thing
250 if (!m_localBackend.IsLocalRegion(destination.RegionID)) 249 if (!m_localBackend.IsLocalRegion(destination.RegionID))
251 return m_remoteConnector.CloseAgent(destination, id, auth_token); 250 return m_remoteConnector.CloseAgent(destination, id, auth_token);
252 251
253 return false; 252 return false;
254 } 253 }
255 254
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 6d4ac39..77fd70b 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
59 59
60 #region ISharedRegionModule 60 #region ISharedRegionModule
61 61
62 public Type ReplaceableInterface 62 public Type ReplaceableInterface
63 { 63 {
64 get { return null; } 64 get { return null; }
65 } 65 }
@@ -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)
@@ -152,7 +153,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
152 public UserAccount GetUserAccount(UUID scopeID, UUID userID) 153 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
153 { 154 {
154 bool inCache = false; 155 bool inCache = false;
155 UserAccount account = m_Cache.Get(userID, out inCache); 156 UserAccount account;
157 account = m_Cache.Get(userID, out inCache);
156 if (inCache) 158 if (inCache)
157 return account; 159 return account;
158 160
@@ -165,7 +167,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
165 public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) 167 public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
166 { 168 {
167 bool inCache = false; 169 bool inCache = false;
168 UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache); 170 UserAccount account;
171 account = m_Cache.Get(firstName + " " + lastName, out inCache);
169 if (inCache) 172 if (inCache)
170 return account; 173 return account;
171 174
@@ -181,6 +184,50 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
181 return UserAccountService.GetUserAccount(scopeID, Email); 184 return UserAccountService.GetUserAccount(scopeID, Email);
182 } 185 }
183 186
187 public List<UserAccount> GetUserAccounts(UUID scopeID, List<string> IDs)
188 {
189 List<UserAccount> ret = new List<UserAccount>();
190 List<string> missing = new List<string>();
191
192 // still another cache..
193 bool inCache = false;
194 UUID uuid = UUID.Zero;
195 UserAccount account;
196 foreach(string id in IDs)
197 {
198 if(UUID.TryParse(id, out uuid))
199 {
200 account = m_Cache.Get(uuid, out inCache);
201 if (inCache)
202 ret.Add(account);
203 else
204 missing.Add(id);
205 }
206 }
207
208 if(missing.Count == 0)
209 return ret;
210
211 List<UserAccount> ext = UserAccountService.GetUserAccounts(scopeID, missing);
212 if(ext != null && ext.Count > 0)
213 {
214 foreach(UserAccount acc in ext)
215 {
216 if(acc != null)
217 {
218 ret.Add(acc);
219 m_Cache.Cache(acc.PrincipalID, acc);
220 }
221 }
222 }
223 return ret;
224 }
225
226 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
227 {
228 return null;
229 }
230
184 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 231 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
185 { 232 {
186 return UserAccountService.GetUserAccounts(scopeID, query); 233 return UserAccountService.GetUserAccounts(scopeID, query);
@@ -203,4 +250,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
203 250
204 #endregion 251 #endregion
205 } 252 }
206} \ No newline at end of file 253}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
index 5aa87d3..b510d0a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
@@ -26,6 +26,8 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Collections.Generic;
29using Nini.Config; 31using Nini.Config;
30using log4net; 32using log4net;
31using Mono.Addins; 33using Mono.Addins;
@@ -34,6 +36,7 @@ using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
36using OpenSim.Services.Connectors; 38using OpenSim.Services.Connectors;
39using OpenSim.Framework;
37 40
38using OpenMetaverse; 41using OpenMetaverse;
39 42
@@ -50,7 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
50 private bool m_Enabled = false; 53 private bool m_Enabled = false;
51 private UserAccountCache m_Cache; 54 private UserAccountCache m_Cache;
52 55
53 public Type ReplaceableInterface 56 public Type ReplaceableInterface
54 { 57 {
55 get { return null; } 58 get { return null; }
56 } 59 }
@@ -103,6 +106,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
103 return; 106 return;
104 107
105 scene.RegisterModuleInterface<IUserAccountService>(this); 108 scene.RegisterModuleInterface<IUserAccountService>(this);
109 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
110
111 scene.EventManager.OnNewClient += OnNewClient;
106 } 112 }
107 113
108 public void RemoveRegion(Scene scene) 114 public void RemoveRegion(Scene scene)
@@ -117,12 +123,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
117 return; 123 return;
118 } 124 }
119 125
126 // When a user actually enters the sim, clear them from
127 // cache so the sim will have the current values for
128 // flags, title, etc. And country, don't forget country!
129 private void OnNewClient(IClientAPI client)
130 {
131 m_Cache.Remove(client.Name);
132 }
133
120 #region Overwritten methods from IUserAccountService 134 #region Overwritten methods from IUserAccountService
121 135
122 public override UserAccount GetUserAccount(UUID scopeID, UUID userID) 136 public override UserAccount GetUserAccount(UUID scopeID, UUID userID)
123 { 137 {
124 bool inCache = false; 138 bool inCache = false;
125 UserAccount account = m_Cache.Get(userID, out inCache); 139 UserAccount account;
140 account = m_Cache.Get(userID, out inCache);
126 if (inCache) 141 if (inCache)
127 return account; 142 return account;
128 143
@@ -135,7 +150,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
135 public override UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) 150 public override UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
136 { 151 {
137 bool inCache = false; 152 bool inCache = false;
138 UserAccount account = m_Cache.Get(firstName + " " + lastName, out inCache); 153 UserAccount account;
154 account = m_Cache.Get(firstName + " " + lastName, out inCache);
139 if (inCache) 155 if (inCache)
140 return account; 156 return account;
141 157
@@ -146,6 +162,45 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
146 return account; 162 return account;
147 } 163 }
148 164
165 public override List<UserAccount> GetUserAccounts(UUID scopeID, List<string> IDs)
166 {
167 List<UserAccount> accs = new List<UserAccount>();
168 List<string> missing = new List<string>();
169
170 UUID uuid = UUID.Zero;
171 UserAccount account;
172 bool inCache = false;
173
174 foreach(string id in IDs)
175 {
176 if(UUID.TryParse(id, out uuid))
177 {
178 account = m_Cache.Get(uuid, out inCache);
179 if (inCache)
180 accs.Add(account);
181 else
182 missing.Add(id);
183 }
184 }
185
186 if(missing.Count > 0)
187 {
188 List<UserAccount> ext = base.GetUserAccounts(scopeID, missing);
189 if(ext != null && ext.Count >0 )
190 {
191 foreach(UserAccount acc in ext)
192 {
193 if(acc != null)
194 {
195 accs.Add(acc);
196 m_Cache.Cache(acc.PrincipalID, acc);
197 }
198 }
199 }
200 }
201 return accs;
202 }
203
149 public override bool StoreUserAccount(UserAccount data) 204 public override bool StoreUserAccount(UserAccount data)
150 { 205 {
151 // This remote connector refuses to serve this method 206 // This remote connector refuses to serve this method
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
index ed52e48..f3572a2 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
@@ -34,68 +34,119 @@ 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_ALIEN_EXPIRATION_SECONDS = 172800; // 48 hours
40 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour!
41 private const double CACHE_NULL_EXPIRATION_SECONDS = 600; // 10minutes
40 42
41// private static readonly ILog m_log = 43// private static readonly ILog m_log =
42// LogManager.GetLogger( 44// LogManager.GetLogger(
43// MethodBase.GetCurrentMethod().DeclaringType); 45// MethodBase.GetCurrentMethod().DeclaringType);
44 46
45 private ExpiringCache<UUID, UserAccount> m_UUIDCache; 47 private ExpiringCache<UUID, UserAccount> m_UUIDCache;
46 private ExpiringCache<string, UUID> m_NameCache; 48 private ExpiringCache<string, UUID> m_NameCache;
49 private object accessLock = new object();
47 50
48 public UserAccountCache() 51 public UserAccountCache()
49 { 52 {
50 m_UUIDCache = new ExpiringCache<UUID, UserAccount>(); 53 m_UUIDCache = new ExpiringCache<UUID, UserAccount>();
51 m_NameCache = new ExpiringCache<string, UUID>(); 54 m_NameCache = new ExpiringCache<string, UUID>();
52 } 55 }
53 56
54 public void Cache(UUID userID, UserAccount account) 57 public void Cache(UUID userID, UserAccount account)
55 { 58 {
56 // Cache even null accounts 59 // Cache even null accounts
57 m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS); 60 lock(accessLock)
58 if (account != null) 61 {
59 m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, CACHE_EXPIRATION_SECONDS); 62 if (account == null)
60 63 m_UUIDCache.AddOrUpdate(userID, null, CACHE_NULL_EXPIRATION_SECONDS);
64 else if(account.LocalToGrid)
65 {
66 m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS);
67 m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, CACHE_EXPIRATION_SECONDS);
68 }
69 else
70 {
71 m_UUIDCache.AddOrUpdate(userID, account, CACHE_ALIEN_EXPIRATION_SECONDS);
72 m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, CACHE_ALIEN_EXPIRATION_SECONDS);
73 }
61 //m_log.DebugFormat("[USER CACHE]: cached user {0}", userID); 74 //m_log.DebugFormat("[USER CACHE]: cached user {0}", userID);
75 }
62 } 76 }
63 77
64 public void Invalidate(UUID userID)
65 {
66 m_UUIDCache.Remove(userID);
67 }
68 78
69 public UserAccount Get(UUID userID, out bool inCache) 79 public UserAccount Get(UUID userID, out bool inCache)
70 { 80 {
71 UserAccount account = null; 81 UserAccount account = null;
72 inCache = false; 82 inCache = false;
73 if (m_UUIDCache.TryGetValue(userID, out account)) 83 lock(accessLock)
74 { 84 {
75 //m_log.DebugFormat("[USER CACHE]: Account {0} {1} found in cache", account.FirstName, account.LastName); 85 if (m_UUIDCache.TryGetValue(userID, out account))
76 inCache = true; 86 {
77 return account; 87 //m_log.DebugFormat("[USER CACHE]: Account {0} {1} found in cache", account.FirstName, account.LastName);
88 inCache = true;
89 return account;
90 }
78 } 91 }
79
80 return null; 92 return null;
81 } 93 }
82 94
83 public UserAccount Get(string name, out bool inCache) 95 public UserAccount Get(string name, out bool inCache)
84 { 96 {
85 inCache = false; 97 inCache = false;
86 if (!m_NameCache.Contains(name)) 98 lock(accessLock)
87 return null; 99 {
100 if (!m_NameCache.Contains(name))
101 return null;
88 102
89 UserAccount account = null; 103 UserAccount account = null;
90 UUID uuid = UUID.Zero; 104 UUID uuid = UUID.Zero;
91 if (m_NameCache.TryGetValue(name, out uuid)) 105 if (m_NameCache.TryGetValue(name, out uuid))
92 if (m_UUIDCache.TryGetValue(uuid, out account))
93 { 106 {
94 inCache = true; 107 if (m_UUIDCache.TryGetValue(uuid, out account))
95 return account; 108 {
109 inCache = true;
110 return account;
111 }
96 } 112 }
97 113 }
98 return null; 114 return null;
99 } 115 }
116
117 public void Invalidate(UUID userID)
118 {
119 m_UUIDCache.Remove(userID);
120 }
121
122 public void Remove(UUID id)
123 {
124 lock(accessLock)
125 {
126 if (!m_UUIDCache.Contains(id))
127 return;
128
129 UserAccount account = null;
130 if (m_UUIDCache.TryGetValue(id, out account) && account != null)
131 m_NameCache.Remove(account.Name);
132 m_UUIDCache.Remove(id);
133 }
134 }
135
136 public void Remove(string name)
137 {
138 lock(accessLock)
139 {
140 if (!m_NameCache.Contains(name))
141 return;
142
143 UUID uuid = UUID.Zero;
144 if (m_NameCache.TryGetValue(name, out uuid))
145 {
146 m_NameCache.Remove(name);
147 m_UUIDCache.Remove(uuid);
148 }
149 }
150 }
100 } 151 }
101} 152}
diff --git a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
index f567cab..081439a 100644
--- a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
+++ b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.CoreModules.World
44 public class AccessModule : ISharedRegionModule 44 public class AccessModule : ISharedRegionModule
45 { 45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private List<Scene> m_SceneList = new List<Scene>(); 48 private List<Scene> m_SceneList = new List<Scene>();
49 49
50 public void Initialise(IConfigSource config) 50 public void Initialise(IConfigSource config)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 9c6706f..41515c0 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -40,6 +40,7 @@ using OpenSim.Framework.Monitoring;
40using OpenSim.Framework.Serialization; 40using OpenSim.Framework.Serialization;
41using OpenSim.Framework.Serialization.External; 41using OpenSim.Framework.Serialization.External;
42using OpenSim.Region.CoreModules.World.Terrain; 42using OpenSim.Region.CoreModules.World.Terrain;
43using OpenSim.Region.CoreModules.World.Land;
43using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.Framework.Scenes.Serialization; 46using OpenSim.Region.Framework.Scenes.Serialization;
@@ -76,14 +77,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
76 SceneObjects = new List<SceneObjectGroup>(); 77 SceneObjects = new List<SceneObjectGroup>();
77 } 78 }
78 } 79 }
79 80
80 81
81 /// <summary> 82 /// <summary>
82 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version 83 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
83 /// bumps here should be compatible. 84 /// bumps here should be compatible.
84 /// </summary> 85 /// </summary>
85 public static int MAX_MAJOR_VERSION = 1; 86 public static int MAX_MAJOR_VERSION = 1;
86 87
87 /// <summary> 88 /// <summary>
88 /// Has the control file been loaded for this archive? 89 /// Has the control file been loaded for this archive?
89 /// </summary> 90 /// </summary>
@@ -126,12 +127,29 @@ namespace OpenSim.Region.CoreModules.World.Archiver
126 /// </value> 127 /// </value>
127 protected float m_rotation = 0f; 128 protected float m_rotation = 0f;
128 129
130 /// <value>
131 /// original oar region size. not using Constants.RegionSize
132 /// </value>
133 protected Vector3 m_incomingRegionSize = new Vector3(256f, 256f, float.MaxValue);
134
135 /// <value>
136 /// Center around which to apply the rotation relative to the original oar position
137 /// </value>
138 protected Vector3 m_rotationCenter = new Vector3(128f, 128f, 0f);
139
140 /// <value>
141 /// Corner 1 of a bounding cuboid which specifies which objects we load from the oar
142 /// </value>
143 protected Vector3 m_boundingOrigin = Vector3.Zero;
144
129 /// <value> 145 /// <value>
130 /// Center around which to apply the rotation relative to the origional oar position 146 /// Size of a bounding cuboid which specifies which objects we load from the oar
131 /// </value> 147 /// </value>
132 protected Vector3 m_rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f); 148 protected Vector3 m_boundingSize = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, float.MaxValue);
133 149
134 protected bool m_noObjects = false; 150 protected bool m_noObjects = false;
151 protected bool m_boundingBox = false;
152 protected bool m_debug = false;
135 153
136 /// <summary> 154 /// <summary>
137 /// Used to cache lookups for valid uuids. 155 /// Used to cache lookups for valid uuids.
@@ -160,10 +178,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
160 178
161 private IAssetService m_assetService = null; 179 private IAssetService m_assetService = null;
162 180
163
164 private UUID m_defaultUser; 181 private UUID m_defaultUser;
165 182
166 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string,object>options) 183 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options)
167 { 184 {
168 m_rootScene = scene; 185 m_rootScene = scene;
169 186
@@ -172,7 +189,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
172 m_defaultUser = (UUID)options["default-user"]; 189 m_defaultUser = (UUID)options["default-user"];
173 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString()); 190 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString());
174 } 191 }
175 else 192 else
176 { 193 {
177 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 194 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
178 } 195 }
@@ -189,8 +206,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
189 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 206 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
190 m_log.Error(e); 207 m_log.Error(e);
191 } 208 }
192 209
193 m_errorMessage = String.Empty; 210 m_errorMessage = String.Empty;
211
194 m_merge = options.ContainsKey("merge"); 212 m_merge = options.ContainsKey("merge");
195 m_forceTerrain = options.ContainsKey("force-terrain"); 213 m_forceTerrain = options.ContainsKey("force-terrain");
196 m_forceParcels = options.ContainsKey("force-parcels"); 214 m_forceParcels = options.ContainsKey("force-parcels");
@@ -199,10 +217,45 @@ namespace OpenSim.Region.CoreModules.World.Archiver
199 m_requestId = requestId; 217 m_requestId = requestId;
200 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero; 218 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
201 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f; 219 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
202 m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
203 : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
204 220
205 // Zero can never be a valid user or group id 221 m_boundingOrigin = Vector3.Zero;
222 m_boundingSize = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, float.MaxValue);
223
224 if (options.ContainsKey("bounding-origin"))
225 {
226 Vector3 boOption = (Vector3)options["bounding-origin"];
227 if (boOption != m_boundingOrigin)
228 {
229 m_boundingOrigin = boOption;
230 }
231 m_boundingBox = true;
232 }
233
234 if (options.ContainsKey("bounding-size"))
235 {
236 Vector3 bsOption = (Vector3)options["bounding-size"];
237 bool clip = false;
238 if (bsOption.X <= 0 || bsOption.X > m_boundingSize.X)
239 {
240 bsOption.X = m_boundingSize.X;
241 clip = true;
242 }
243 if (bsOption.Y <= 0 || bsOption.Y > m_boundingSize.Y)
244 {
245 bsOption.Y = m_boundingSize.Y;
246 clip = true;
247 }
248 if (bsOption != m_boundingSize)
249 {
250 m_boundingSize = bsOption;
251 m_boundingBox = true;
252 }
253 if (clip) m_log.InfoFormat("[ARCHIVER]: The bounding cube specified is larger than the destination region! Clipping to {0}.", m_boundingSize.ToString());
254 }
255
256 m_debug = options.ContainsKey("debug");
257
258 // Zero can never be a valid user id (or group)
206 m_validUserUuids[UUID.Zero] = false; 259 m_validUserUuids[UUID.Zero] = false;
207 m_validGroupUuids[UUID.Zero] = false; 260 m_validGroupUuids[UUID.Zero] = false;
208 261
@@ -210,7 +263,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
210 m_assetService = m_rootScene.AssetService; 263 m_assetService = m_rootScene.AssetService;
211 } 264 }
212 265
213 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object>options) 266 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object> options)
214 { 267 {
215 m_rootScene = scene; 268 m_rootScene = scene;
216 m_loadPath = null; 269 m_loadPath = null;
@@ -220,7 +273,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
220 m_requestId = requestId; 273 m_requestId = requestId;
221 274
222 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 275 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
223 276
224 // Zero can never be a valid user id 277 // Zero can never be a valid user id
225 m_validUserUuids[UUID.Zero] = false; 278 m_validUserUuids[UUID.Zero] = false;
226 279
@@ -233,6 +286,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
233 /// </summary> 286 /// </summary>
234 public void DearchiveRegion() 287 public void DearchiveRegion()
235 { 288 {
289 DearchiveRegion(true);
290 }
291
292 public void DearchiveRegion(bool shouldStartScripts)
293 {
236 int successfulAssetRestores = 0; 294 int successfulAssetRestores = 0;
237 int failedAssetRestores = 0; 295 int failedAssetRestores = 0;
238 296
@@ -255,7 +313,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
255 { 313 {
256 //m_log.DebugFormat( 314 //m_log.DebugFormat(
257 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); 315 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
258 316
259 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 317 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
260 continue; 318 continue;
261 319
@@ -301,11 +359,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
301 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) 359 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
302 { 360 {
303 LoadRegionSettings(scene, filePath, data, dearchivedScenes); 361 LoadRegionSettings(scene, filePath, data, dearchivedScenes);
304 } 362 }
305 else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH) && (!m_merge || m_forceParcels)) 363 else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH) && (!m_merge || m_forceParcels))
306 { 364 {
307 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); 365 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
308 } 366 }
309 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 367 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
310 { 368 {
311 // Ignore, because we already read the control file 369 // Ignore, because we already read the control file
@@ -353,7 +411,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
353 { 411 {
354 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels); 412 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
355 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects); 413 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
356 414
357 // Inform any interested parties that the region has changed. We waited until now so that all 415 // Inform any interested parties that the region has changed. We waited until now so that all
358 // of the region's objects will be loaded when we send this notification. 416 // of the region's objects will be loaded when we send this notification.
359 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>(); 417 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
@@ -372,22 +430,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
372 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so 430 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
373 // that users can enter the scene. If we allow the scripts to start in the loop above 431 // that users can enter the scene. If we allow the scripts to start in the loop above
374 // then they significantly increase the time until the OAR finishes loading. 432 // then they significantly increase the time until the OAR finishes loading.
375 WorkManager.RunInThread(o => 433 if (shouldStartScripts)
376 { 434 {
377 Thread.Sleep(15000); 435 WorkManager.RunInThread(o =>
378 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
379
380 foreach (DearchiveContext sceneContext in sceneContexts.Values)
381 { 436 {
382 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) 437 Thread.Sleep(15000);
438 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
439
440 foreach (DearchiveContext sceneContext in sceneContexts.Values)
383 { 441 {
384 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart 442 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
385 sceneObject.ResumeScripts(); 443 {
386 } 444 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
445 sceneObject.ResumeScripts();
446 }
387 447
388 sceneContext.SceneObjects.Clear(); 448 sceneContext.SceneObjects.Clear();
389 } 449 }
390 }, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId)); 450 }, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId));
451 }
391 452
392 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); 453 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
393 454
@@ -418,7 +479,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
418 { 479 {
419 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 480 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
420 continue; 481 continue;
421 482
422 if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 483 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
423 { 484 {
424 LoadControlFile(filePath, data, dearchivedScenes); 485 LoadControlFile(filePath, data, dearchivedScenes);
@@ -435,7 +496,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
435 // If the control file wasn't the first file then reset the read pointer 496 // If the control file wasn't the first file then reset the read pointer
436 if (!firstFile) 497 if (!firstFile)
437 { 498 {
438 m_log.Warn("Control file wasn't the first file in the archive"); 499 m_log.Warn("[ARCHIVER]: Control file wasn't the first file in the archive");
439 if (m_loadStream.CanSeek) 500 if (m_loadStream.CanSeek)
440 { 501 {
441 m_loadStream.Seek(0, SeekOrigin.Begin); 502 m_loadStream.Seek(0, SeekOrigin.Begin);
@@ -452,7 +513,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
452 else 513 else
453 { 514 {
454 // There isn't currently a scenario where this happens, but it's best to add a check just in case 515 // There isn't currently a scenario where this happens, but it's best to add a check just in case
455 throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking"); 516 throw new Exception("[ARCHIVER]: Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
456 } 517 }
457 } 518 }
458 519
@@ -462,9 +523,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
462 firstFile = false; 523 firstFile = false;
463 } 524 }
464 525
465 throw new Exception("Control file not found"); 526 throw new Exception("[ARCHIVER]: Control file not found");
466 } 527 }
467 528
468 /// <summary> 529 /// <summary>
469 /// Load serialized scene objects. 530 /// Load serialized scene objects.
470 /// </summary> 531 /// </summary>
@@ -473,12 +534,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
473 // Reload serialized prims 534 // Reload serialized prims
474 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); 535 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
475 536
476 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation); 537 // Convert rotation to radians
538 double rotation = Math.PI * m_rotation / 180f;
539
540 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, (float)rotation);
477 541
478 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; 542 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
479 543
480 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); 544 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
481 int sceneObjectsLoadedCount = 0; 545 int sceneObjectsLoadedCount = 0;
546 Vector3 boundingExtent = new Vector3(m_boundingOrigin.X + m_boundingSize.X, m_boundingOrigin.Y + m_boundingSize.Y, m_boundingOrigin.Z + m_boundingSize.Z);
482 547
483 foreach (string serialisedSceneObject in serialisedSceneObjects) 548 foreach (string serialisedSceneObject in serialisedSceneObjects)
484 { 549 {
@@ -488,7 +553,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
488 // Really large xml files (multi megabyte) appear to cause 553 // Really large xml files (multi megabyte) appear to cause
489 // memory problems 554 // memory problems
490 // when loading the xml. But don't enable this check yet 555 // when loading the xml. But don't enable this check yet
491 556
492 if (serialisedSceneObject.Length > 5000000) 557 if (serialisedSceneObject.Length > 5000000)
493 { 558 {
494 m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);"); 559 m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);");
@@ -498,31 +563,52 @@ namespace OpenSim.Region.CoreModules.World.Archiver
498 563
499 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); 564 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
500 565
566 Vector3 pos = sceneObject.AbsolutePosition;
567 if (m_debug)
568 m_log.DebugFormat("[ARCHIVER]: Loading object from OAR with original scene position {0}.", pos.ToString());
569
501 // Happily this does not do much to the object since it hasn't been added to the scene yet 570 // Happily this does not do much to the object since it hasn't been added to the scene yet
502 if (!sceneObject.IsAttachment) 571 if (!sceneObject.IsAttachment)
503 { 572 {
504 if (m_displacement != Vector3.Zero || m_rotation != 0f) 573 if (m_rotation != 0f)
505 { 574 {
506 Vector3 pos = sceneObject.AbsolutePosition; 575 //fix the rotation center to the middle of the incoming region now as it's otherwise hopelessly confusing on varRegions
507 if (m_rotation != 0f) 576 //as it only works with objects and terrain (using old Merge method) and not parcels
508 { 577 m_rotationCenter.X = m_incomingRegionSize.X / 2;
509 // Rotate the object 578 m_rotationCenter.Y = m_incomingRegionSize.Y / 2;
510 sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation; 579
511 // Get object position relative to rotation axis 580 // Rotate the object
512 Vector3 offset = pos - m_rotationCenter; 581 sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
513 // Rotate the object position 582 // Get object position relative to rotation axis
514 offset *= rot; 583 Vector3 offset = pos - m_rotationCenter;
515 // Restore the object position back to relative to the region 584 // Rotate the object position
516 pos = m_rotationCenter + offset; 585 offset *= rot;
517 } 586 // Restore the object position back to relative to the region
518 if (m_displacement != Vector3.Zero) 587 pos = m_rotationCenter + offset;
588 if (m_debug) m_log.DebugFormat("[ARCHIVER]: After rotation, object from OAR is at scene position {0}.", pos.ToString());
589 }
590 if (m_boundingBox)
591 {
592 if (pos.X < m_boundingOrigin.X || pos.X >= boundingExtent.X
593 || pos.Y < m_boundingOrigin.Y || pos.Y >= boundingExtent.Y
594 || pos.Z < m_boundingOrigin.Z || pos.Z >= boundingExtent.Z)
519 { 595 {
520 pos += m_displacement; 596 if (m_debug) m_log.DebugFormat("[ARCHIVER]: Skipping object from OAR in scene because it's position {0} is outside of bounding cube.", pos.ToString());
597 continue;
521 } 598 }
522 sceneObject.AbsolutePosition = pos; 599 //adjust object position to be relative to <0,0> so we can apply the displacement
600 pos.X -= m_boundingOrigin.X;
601 pos.Y -= m_boundingOrigin.Y;
602 }
603 if (m_displacement != Vector3.Zero)
604 {
605 pos += m_displacement;
606 if (m_debug) m_log.DebugFormat("[ARCHIVER]: After displacement, object from OAR is at scene position {0}.", pos.ToString());
523 } 607 }
608 sceneObject.AbsolutePosition = pos;
524 } 609 }
525 610 if (m_debug)
611 m_log.DebugFormat("[ARCHIVER]: Placing object from OAR in scene at position {0}. ", pos.ToString());
526 612
527 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); 613 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
528 614
@@ -554,11 +640,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
554 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount; 640 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;
555 641
556 if (ignoredObjects > 0) 642 if (ignoredObjects > 0)
557 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); 643 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene or were out of bounds", ignoredObjects);
558 644
559 if (oldTelehubUUID != UUID.Zero) 645 if (oldTelehubUUID != UUID.Zero)
560 { 646 {
561 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); 647 m_log.WarnFormat("[ARCHIVER]: Telehub object not found: {0}", oldTelehubUUID);
562 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; 648 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
563 scene.RegionInfo.RegionSettings.ClearSpawnPoints(); 649 scene.RegionInfo.RegionSettings.ClearSpawnPoints();
564 } 650 }
@@ -600,6 +686,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
600 // being no copy/no mod for everyone 686 // being no copy/no mod for everyone
601 lock (part.TaskInventory) 687 lock (part.TaskInventory)
602 { 688 {
689/* avination code disabled for opensim
690 // And zap any troublesome sit target information
691 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
692 part.SitTargetPosition = new Vector3(0, 0, 0);
693*/
694 // Fix ownership/creator of inventory items
695 // Not doing so results in inventory items
696 // being no copy/no mod for everyone
697 part.TaskInventory.LockItemsForRead(true);
698
603 TaskInventoryDictionary inv = part.TaskInventory; 699 TaskInventoryDictionary inv = part.TaskInventory;
604 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 700 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
605 { 701 {
@@ -620,11 +716,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
620 if (!ResolveGroupUuid(kvp.Value.GroupID)) 716 if (!ResolveGroupUuid(kvp.Value.GroupID))
621 kvp.Value.GroupID = UUID.Zero; 717 kvp.Value.GroupID = UUID.Zero;
622 } 718 }
719 part.TaskInventory.LockItemsForRead(false);
720
623 } 721 }
624 } 722 }
625 } 723 }
626 724
627
628 /// <summary> 725 /// <summary>
629 /// Load serialized parcels. 726 /// Load serialized parcels.
630 /// </summary> 727 /// </summary>
@@ -635,17 +732,88 @@ namespace OpenSim.Region.CoreModules.World.Archiver
635 // Reload serialized parcels 732 // Reload serialized parcels
636 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); 733 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
637 List<LandData> landData = new List<LandData>(); 734 List<LandData> landData = new List<LandData>();
735 ILandObject landObject = scene.RequestModuleInterface<ILandObject>();
736 List<ILandObject> parcels;
737 Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
738 Vector2 displacement = new Vector2(m_displacement.X, m_displacement.Y);
739 Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
740 Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
741 Vector2 regionSize = new Vector2(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY);
742
743 // Gather any existing parcels before we add any more. Later as we add parcels we can check if the new parcel
744 // data overlays any of the old data, and we can modify and remove (if empty) the old parcel so that there's no conflict
745 parcels = scene.LandChannel.AllParcels();
746
638 foreach (string serialisedParcel in serialisedParcels) 747 foreach (string serialisedParcel in serialisedParcels)
639 { 748 {
640 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); 749 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
750 bool overrideRegionSize = true; //use the src land parcel data size not the dst region size
751 bool isEmptyNow;
752 Vector3 AABBMin;
753 Vector3 AABBMax;
754
755 // create a new LandObject that we can use to manipulate the incoming source parcel data
756 // this is ok, but just beware that some of the LandObject functions (that we haven't used here) still
757 // assume we're always using the destination region size
758 LandData ld = new LandData();
759 landObject = new LandObject(ld, scene);
760 landObject.LandData = parcel;
761
762 bool[,] srcLandBitmap = landObject.ConvertBytesToLandBitmap(overrideRegionSize);
763 if (landObject.IsLandBitmapEmpty(srcLandBitmap))
764 {
765 m_log.InfoFormat("[ARCHIVER]: Skipping source parcel {0} with GlobalID: {1} LocalID: {2} that has no claimed land.",
766 parcel.Name, parcel.GlobalID, parcel.LocalID);
767 continue;
768 }
769 //m_log.DebugFormat("[ARCHIVER]: Showing claimed land for source parcel: {0} with GlobalID: {1} LocalID: {2}.",
770 // parcel.Name, parcel.GlobalID, parcel.LocalID);
771 //landObject.DebugLandBitmap(srcLandBitmap);
772
773 bool[,] dstLandBitmap = landObject.RemapLandBitmap(srcLandBitmap, displacement, m_rotation, boundingOrigin, boundingSize, regionSize, out isEmptyNow, out AABBMin, out AABBMax);
774 if (isEmptyNow)
775 {
776 m_log.WarnFormat("[ARCHIVER]: Not adding destination parcel {0} with GlobalID: {1} LocalID: {2} because, after applying rotation, bounding and displacement, it has no claimed land.",
777 parcel.Name, parcel.GlobalID, parcel.LocalID);
778 continue;
779 }
780 //m_log.DebugFormat("[ARCHIVER]: Showing claimed land for destination parcel: {0} with GlobalID: {1} LocalID: {2} after applying rotation, bounding and displacement.",
781 // parcel.Name, parcel.GlobalID, parcel.LocalID);
782 //landObject.DebugLandBitmap(dstLandBitmap);
783
784 landObject.LandBitmap = dstLandBitmap;
785 parcel.Bitmap = landObject.ConvertLandBitmapToBytes();
786 parcel.AABBMin = AABBMin;
787 parcel.AABBMax = AABBMax;
641 788
642 if (m_displacement != Vector3.Zero) 789 if (m_merge)
643 { 790 {
644 Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f); 791 // give the remapped parcel a new GlobalID, in case we're using the same OAR twice and a bounding cube, displacement and --merge
645 parcel.AABBMin += parcelDisp; 792 parcel.GlobalID = UUID.Random();
646 parcel.AABBMax += parcelDisp; 793
794 //now check if the area of this new incoming parcel overlays an area in any existing parcels
795 //and if so modify or lose the existing parcels
796 for (int i = 0; i < parcels.Count; i++)
797 {
798 if (parcels[i] != null)
799 {
800 bool[,] modLandBitmap = parcels[i].ConvertBytesToLandBitmap(overrideRegionSize);
801 modLandBitmap = parcels[i].RemoveFromLandBitmap(modLandBitmap, dstLandBitmap, out isEmptyNow, out AABBMin, out AABBMax);
802 if (isEmptyNow)
803 {
804 parcels[i] = null;
805 }
806 else
807 {
808 parcels[i].LandBitmap = modLandBitmap;
809 parcels[i].LandData.Bitmap = parcels[i].ConvertLandBitmapToBytes();
810 parcels[i].LandData.AABBMin = AABBMin;
811 parcels[i].LandData.AABBMax = AABBMax;
812 }
813 }
814 }
647 } 815 }
648 816
649 // Validate User and Group UUID's 817 // Validate User and Group UUID's
650 818
651 if (!ResolveGroupUuid(parcel.GroupID)) 819 if (!ResolveGroupUuid(parcel.GroupID))
@@ -679,19 +847,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
679 } 847 }
680 parcel.ParcelAccessList = accessList; 848 parcel.ParcelAccessList = accessList;
681 849
682// m_log.DebugFormat( 850 if (m_debug) m_log.DebugFormat("[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
683// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}", 851 parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
684// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area); 852
685
686 landData.Add(parcel); 853 landData.Add(parcel);
687 } 854 }
688 855
689 if (!m_merge) 856 if (m_merge)
690 { 857 {
691 bool setupDefaultParcel = (landData.Count == 0); 858 for (int i = 0; i < parcels.Count; i++) //if merging then we need to also add back in any existing parcels
692 scene.LandChannel.Clear(setupDefaultParcel); 859 {
860 if (parcels[i] != null) landData.Add(parcels[i].LandData);
861 }
693 } 862 }
694 863
864 m_log.InfoFormat("[ARCHIVER]: Clearing {0} parcels.", parcels.Count);
865 bool setupDefaultParcel = (landData.Count == 0);
866 scene.LandChannel.Clear(setupDefaultParcel);
695 scene.EventManager.TriggerIncomingLandDataFromStorage(landData); 867 scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
696 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); 868 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
697 } 869 }
@@ -772,6 +944,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
772 944
773 if (m_assetService.GetMetadata(uuid) != null) 945 if (m_assetService.GetMetadata(uuid) != null)
774 { 946 {
947 sbyte asype = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
948 if(asype == -2)
949 {
950
951 }
952
775 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); 953 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
776 return true; 954 return true;
777 } 955 }
@@ -780,6 +958,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
780 { 958 {
781 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; 959 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
782 960
961 if(assetType == -2)
962 {
963
964 }
783 if (assetType == (sbyte)AssetType.Unknown) 965 if (assetType == (sbyte)AssetType.Unknown)
784 { 966 {
785 m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid); 967 m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
@@ -792,7 +974,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
792 ModifySceneObject(m_rootScene, sog); 974 ModifySceneObject(m_rootScene, sog);
793 return true; 975 return true;
794 }); 976 });
795 977
796 if (data == null) 978 if (data == null)
797 return false; 979 return false;
798 } 980 }
@@ -898,7 +1080,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
898 currentRegionSettings.Save(); 1080 currentRegionSettings.Save();
899 1081
900 scene.TriggerEstateSunUpdate(); 1082 scene.TriggerEstateSunUpdate();
901 1083
902 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>(); 1084 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
903 if (estateModule != null) 1085 if (estateModule != null)
904 estateModule.sendRegionHandshakeToAll(); 1086 estateModule.sendRegionHandshakeToAll();
@@ -918,13 +1100,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
918 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) 1100 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
919 { 1101 {
920 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); 1102 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
921
922 using (MemoryStream ms = new MemoryStream(data)) 1103 using (MemoryStream ms = new MemoryStream(data))
923 { 1104 {
924 if (m_displacement != Vector3.Zero || m_rotation != 0f) 1105 if (m_displacement != Vector3.Zero || m_rotation != 0f || m_boundingBox)
925 { 1106 {
926 Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y); 1107 Vector2 boundingOrigin = new Vector2(m_boundingOrigin.X, m_boundingOrigin.Y);
927 terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms); 1108 Vector2 boundingSize = new Vector2(m_boundingSize.X, m_boundingSize.Y);
1109 terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, boundingOrigin, boundingSize, ms); ;
928 } 1110 }
929 else 1111 else
930 { 1112 {
@@ -948,6 +1130,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
948 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 1130 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
949 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 1131 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
950 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); 1132 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
1133 xtr.ProhibitDtd = true;
951 1134
952 // Loaded metadata will be empty if no information exists in the archive 1135 // Loaded metadata will be empty if no information exists in the archive
953 dearchivedScenes.LoadedCreationDateTime = 0; 1136 dearchivedScenes.LoadedCreationDateTime = 0;
@@ -955,16 +1138,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
955 1138
956 bool multiRegion = false; 1139 bool multiRegion = false;
957 1140
958 while (xtr.Read()) 1141 while (xtr.Read())
959 { 1142 {
960 if (xtr.NodeType == XmlNodeType.Element) 1143 if (xtr.NodeType == XmlNodeType.Element)
961 { 1144 {
962 if (xtr.Name.ToString() == "archive") 1145 if (xtr.Name.ToString() == "archive")
963 { 1146 {
964 int majorVersion = int.Parse(xtr["major_version"]); 1147 int majorVersion = int.Parse(xtr["major_version"]);
965 int minorVersion = int.Parse(xtr["minor_version"]); 1148 int minorVersion = int.Parse(xtr["minor_version"]);
966 string version = string.Format("{0}.{1}", majorVersion, minorVersion); 1149 string version = string.Format("{0}.{1}", majorVersion, minorVersion);
967 1150
968 if (majorVersion > MAX_MAJOR_VERSION) 1151 if (majorVersion > MAX_MAJOR_VERSION)
969 { 1152 {
970 throw new Exception( 1153 throw new Exception(
@@ -972,15 +1155,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
972 "The OAR you are trying to load has major version number of {0} but this version of OpenSim can only load OARs with major version number {1} and below", 1155 "The OAR you are trying to load has major version number of {0} but this version of OpenSim can only load OARs with major version number {1} and below",
973 majorVersion, MAX_MAJOR_VERSION)); 1156 majorVersion, MAX_MAJOR_VERSION));
974 } 1157 }
975 1158
976 m_log.InfoFormat("[ARCHIVER]: Loading OAR with version {0}", version); 1159 m_log.InfoFormat("[ARCHIVER]: Loading OAR with version {0}", version);
977 } 1160 }
978 if (xtr.Name.ToString() == "datetime") 1161 else if (xtr.Name.ToString() == "datetime")
979 { 1162 {
980 int value; 1163 int value;
981 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) 1164 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
982 dearchivedScenes.LoadedCreationDateTime = value; 1165 dearchivedScenes.LoadedCreationDateTime = value;
983 } 1166 }
984 else if (xtr.Name.ToString() == "row") 1167 else if (xtr.Name.ToString() == "row")
985 { 1168 {
986 multiRegion = true; 1169 multiRegion = true;
@@ -994,13 +1177,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver
994 { 1177 {
995 string id = xtr.ReadElementContentAsString(); 1178 string id = xtr.ReadElementContentAsString();
996 dearchivedScenes.DefaultOriginalID = id; 1179 dearchivedScenes.DefaultOriginalID = id;
997 if (multiRegion) 1180 if(multiRegion)
998 dearchivedScenes.SetRegionOriginalID(id); 1181 dearchivedScenes.SetRegionOriginalID(id);
999 } 1182 }
1000 else if (xtr.Name.ToString() == "dir") 1183 else if (xtr.Name.ToString() == "dir")
1001 { 1184 {
1002 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); 1185 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
1003 } 1186 }
1187 else if (xtr.Name.ToString() == "size_in_meters")
1188 {
1189 Vector3 value;
1190 string size = "<" + xtr.ReadElementContentAsString() + ",0>";
1191 if (Vector3.TryParse(size, out value))
1192 {
1193 m_incomingRegionSize = value;
1194 if(multiRegion)
1195 dearchivedScenes.SetRegionSize(m_incomingRegionSize);
1196 m_log.DebugFormat("[ARCHIVER]: Found region_size info {0}",
1197 m_incomingRegionSize.ToString());
1198 }
1199 }
1004 } 1200 }
1005 } 1201 }
1006 1202
@@ -1012,9 +1208,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
1012 dearchivedScenes.StartRegion(); 1208 dearchivedScenes.StartRegion();
1013 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID); 1209 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
1014 dearchivedScenes.SetRegionDirectory(""); 1210 dearchivedScenes.SetRegionDirectory("");
1211 dearchivedScenes.SetRegionSize(m_incomingRegionSize);
1015 } 1212 }
1016 1213
1017 ControlFileLoaded = true; 1214 ControlFileLoaded = true;
1215 if(xtr != null)
1216 xtr.Close();
1018 1217
1019 return dearchivedScenes; 1218 return dearchivedScenes;
1020 } 1219 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
index d8dace2..2fb4426 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
50 /// The inner dictionaries contain each row's regions (key: X coordinate). 50 /// The inner dictionaries contain each row's regions (key: X coordinate).
51 /// </summary> 51 /// </summary>
52 public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; } 52 public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; }
53 53
54 /// <summary> 54 /// <summary>
55 /// The subdirectory where each region is stored in the archive. 55 /// The subdirectory where each region is stored in the archive.
56 /// </summary> 56 /// </summary>
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
152 } 152 }
153 } 153 }
154 } 154 }
155 155
156 /// <summary> 156 /// <summary>
157 /// Returns the scene at position 'location'. 157 /// Returns the scene at position 'location'.
158 /// </summary> 158 /// </summary>
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index cb2c7f1..ec273d6 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -60,8 +60,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
60 /// <summary> 60 /// <summary>
61 /// The minimum major version of OAR that we can write. 61 /// The minimum major version of OAR that we can write.
62 /// </summary> 62 /// </summary>
63 public static int MIN_MAJOR_VERSION = 0; 63 public static int MIN_MAJOR_VERSION = 0;
64 64
65 /// <summary> 65 /// <summary>
66 /// The maximum major version of OAR that we can write. 66 /// The maximum major version of OAR that we can write.
67 /// </summary> 67 /// </summary>
@@ -112,7 +112,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
112 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); 112 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
113 } 113 }
114 } 114 }
115 115
116 /// <summary> 116 /// <summary>
117 /// Constructor. 117 /// Constructor.
118 /// </summary> 118 /// </summary>
@@ -181,11 +181,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
181 // Archive the regions 181 // Archive the regions
182 182
183 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>(); 183 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
184 HashSet<UUID> failedIDs = new HashSet<UUID>();
185 HashSet<UUID> uncertainAssetsUUIDs = new HashSet<UUID>();
184 186
185 scenesGroup.ForEachScene(delegate(Scene scene) 187 scenesGroup.ForEachScene(delegate(Scene scene)
186 { 188 {
187 string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; 189 string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
188 ArchiveOneRegion(scene, regionDir, assetUuids); 190 ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs);
189 }); 191 });
190 192
191 // Archive the assets 193 // Archive the assets
@@ -193,23 +195,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver
193 if (SaveAssets) 195 if (SaveAssets)
194 { 196 {
195 m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); 197 m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
196 198
197 // Asynchronously request all the assets required to perform this archive operation 199 AssetsRequest ar = new AssetsRequest(
198 AssetsRequest ar
199 = new AssetsRequest(
200 new AssetsArchiver(m_archiveWriter), assetUuids, 200 new AssetsArchiver(m_archiveWriter), assetUuids,
201 failedIDs.Count,
201 m_rootScene.AssetService, m_rootScene.UserAccountService, 202 m_rootScene.AssetService, m_rootScene.UserAccountService,
202 m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); 203 m_rootScene.RegionInfo.ScopeID, options, null);
203 204 ar.Execute();
204 WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request"); 205 assetUuids = null;
205
206 // CloseArchive() will be called from ReceivedAllAssets()
207 } 206 }
208 else 207 else
209 { 208 {
210 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); 209 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
211 CloseArchive(string.Empty); 210// CloseArchive(string.Empty);
212 } 211 }
212 CloseArchive(string.Empty);
213 } 213 }
214 catch (Exception e) 214 catch (Exception e)
215 { 215 {
@@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
218 } 218 }
219 } 219 }
220 220
221 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids) 221 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids,
222 HashSet<UUID> failedIDs, HashSet<UUID> uncertainAssetsUUIDs)
222 { 223 {
223 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name); 224 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name);
224 225
@@ -226,7 +227,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
226 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 227 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
227 228
228 int numObjectsSkippedPermissions = 0; 229 int numObjectsSkippedPermissions = 0;
229 230
230 // Filter entities so that we only have scene objects. 231 // Filter entities so that we only have scene objects.
231 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods 232 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
232 // end up having to do this 233 // end up having to do this
@@ -237,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
237 { 238 {
238 SceneObjectGroup sceneObject = (SceneObjectGroup)entity; 239 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
239 240
240 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) 241 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment && !sceneObject.IsTemporary && !sceneObject.inTransit)
241 { 242 {
242 if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule)) 243 if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule))
243 { 244 {
@@ -254,17 +255,39 @@ namespace OpenSim.Region.CoreModules.World.Archiver
254 255
255 if (SaveAssets) 256 if (SaveAssets)
256 { 257 {
257 UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids); 258 UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids, failedIDs, uncertainAssetsUUIDs);
258 int prevAssets = assetUuids.Count; 259 int prevAssets = assetUuids.Count;
259 260
260 foreach (SceneObjectGroup sceneObject in sceneObjects) 261 foreach (SceneObjectGroup sceneObject in sceneObjects)
262 {
263 int curErrorCntr = assetGatherer.ErrorCount;
264 int possible = assetGatherer.possibleNotAssetCount;
261 assetGatherer.AddForInspection(sceneObject); 265 assetGatherer.AddForInspection(sceneObject);
266 assetGatherer.GatherAll();
267 curErrorCntr = assetGatherer.ErrorCount - curErrorCntr;
268 possible = assetGatherer.possibleNotAssetCount - possible;
269 if(curErrorCntr > 0)
270 {
271 m_log.ErrorFormat("[ARCHIVER]: object {0} '{1}', at {2}, contains {3} references to missing or damaged assets, or not a problem.",
272 sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), curErrorCntr);
273//// if(possible > 0)
274//// m_log.WarnFormat("[ARCHIVER Warning]: object also contains {0} references that may be to missing or damaged assets or not a problem", possible);
275 }
276//// else if(possible > 0)
277//// {
278//// m_log.WarnFormat("[ARCHIVER Warning]: object {0} '{1}', at {2}, contains {3} references that may be to missing or damaged assets or not a problem",
279//// sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), possible);
280//// }
281 }
262 282
263 assetGatherer.GatherAll(); 283 assetGatherer.GatherAll();
264 284
285 int errors = assetGatherer.FailedUUIDs.Count;
265 m_log.DebugFormat( 286 m_log.DebugFormat(
266 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", 287 "[ARCHIVER]: {0} region scene objects to save reference {1} possible assets",
267 sceneObjects.Count, assetUuids.Count - prevAssets); 288 sceneObjects.Count, assetUuids.Count - prevAssets + errors);
289 if(errors > 0)
290 m_log.DebugFormat("[ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
268 } 291 }
269 292
270 if (numObjectsSkippedPermissions > 0) 293 if (numObjectsSkippedPermissions > 0)
@@ -276,16 +299,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
276 299
277 // Make sure that we also request terrain texture assets 300 // Make sure that we also request terrain texture assets
278 RegionSettings regionSettings = scene.RegionInfo.RegionSettings; 301 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
279 302
280 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) 303 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
281 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture; 304 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
282 305
283 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) 306 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
284 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture; 307 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
285 308
286 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) 309 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
287 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture; 310 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
288 311
289 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) 312 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
290 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture; 313 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
291 314
@@ -398,18 +421,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
398// string[] parts = m_options["version"].ToString().Split('.'); 421// string[] parts = m_options["version"].ToString().Split('.');
399// if (parts.Length >= 1) 422// if (parts.Length >= 1)
400// { 423// {
401// majorVersion = Int32.Parse(parts[0]); 424// majorVersion = Int32.Parse(parts[0]);
402// 425//
403// if (parts.Length >= 2) 426// if (parts.Length >= 2)
404// minorVersion = Int32.Parse(parts[1]); 427// minorVersion = Int32.Parse(parts[1]);
405// } 428// }
406// } 429// }
407// 430//
408// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) 431// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
409// { 432// {
410// throw new Exception( 433// throw new Exception(
411// string.Format( 434// string.Format(
412// "OAR version number for save must be between {0} and {1}", 435// "OAR version number for save must be between {0} and {1}",
413// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); 436// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
414// } 437// }
415// else if (majorVersion == MAX_MAJOR_VERSION) 438// else if (majorVersion == MAX_MAJOR_VERSION)
@@ -420,9 +443,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
420// else if (majorVersion == MIN_MAJOR_VERSION) 443// else if (majorVersion == MIN_MAJOR_VERSION)
421// { 444// {
422// // Force 0.4 445// // Force 0.4
423// minorVersion = 4; 446// minorVersion = 4;
424// } 447// }
425 448
426 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); 449 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
427 if (majorVersion == 1) 450 if (majorVersion == 1)
428 { 451 {
@@ -430,7 +453,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
430 } 453 }
431 454
432 String s; 455 String s;
433 456
434 using (StringWriter sw = new StringWriter()) 457 using (StringWriter sw = new StringWriter())
435 { 458 {
436 using (XmlTextWriter xtw = new XmlTextWriter(sw)) 459 using (XmlTextWriter xtw = new XmlTextWriter(sw))
@@ -440,7 +463,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
440 xtw.WriteStartElement("archive"); 463 xtw.WriteStartElement("archive");
441 xtw.WriteAttributeString("major_version", majorVersion.ToString()); 464 xtw.WriteAttributeString("major_version", majorVersion.ToString());
442 xtw.WriteAttributeString("minor_version", minorVersion.ToString()); 465 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
443 466
444 xtw.WriteStartElement("creation_info"); 467 xtw.WriteStartElement("creation_info");
445 DateTime now = DateTime.UtcNow; 468 DateTime now = DateTime.UtcNow;
446 TimeSpan t = now - new DateTime(1970, 1, 1); 469 TimeSpan t = now - new DateTime(1970, 1, 1);
@@ -448,7 +471,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
448 if (!MultiRegionFormat) 471 if (!MultiRegionFormat)
449 xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); 472 xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString());
450 xtw.WriteEndElement(); 473 xtw.WriteEndElement();
451 474
452 xtw.WriteElementString("assets_included", SaveAssets.ToString()); 475 xtw.WriteElementString("assets_included", SaveAssets.ToString());
453 476
454 if (MultiRegionFormat) 477 if (MultiRegionFormat)
@@ -463,7 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
463 } 486 }
464 487
465 xtw.WriteEndElement(); 488 xtw.WriteEndElement();
466 489
467 xtw.Flush(); 490 xtw.Flush();
468 } 491 }
469 492
@@ -522,22 +545,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
522 545
523 protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) 546 protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw)
524 { 547 {
525 bool isMegaregion;
526 Vector2 size; 548 Vector2 size;
527 549
528 IRegionCombinerModule rcMod = scene.RequestModuleInterface<IRegionCombinerModule>(); 550 size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
529 551
530 if (rcMod != null)
531 isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID);
532 else
533 isMegaregion = false;
534
535 if (isMegaregion)
536 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
537 else
538 size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
539
540 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
541 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); 552 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
542 } 553 }
543 554
@@ -560,7 +571,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
560 foreach (ILandObject lo in landObjects) 571 foreach (ILandObject lo in landObjects)
561 { 572 {
562 LandData landData = lo.LandData; 573 LandData landData = lo.LandData;
563 string landDataPath 574 string landDataPath
564 = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData)); 575 = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData));
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); 576 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 } 577 }
@@ -584,17 +595,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
584 foreach (SceneObjectGroup sceneObject in sceneObjects) 595 foreach (SceneObjectGroup sceneObject in sceneObjects)
585 { 596 {
586 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); 597 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
587 598 if(sceneObject.IsDeleted || sceneObject.inTransit)
599 continue;
588 string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); 600 string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
589 string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); 601 string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
590 m_archiveWriter.WriteFile(objectPath, serializedObject); 602 m_archiveWriter.WriteFile(objectPath, serializedObject);
591 } 603 }
592 } 604 }
593 605
594 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut) 606 protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids, bool timedOut)
595 { 607 {
596 string errorMessage; 608 string errorMessage;
597 609
598 if (timedOut) 610 if (timedOut)
599 { 611 {
600 errorMessage = "Loading assets timed out"; 612 errorMessage = "Loading assets timed out";
@@ -612,10 +624,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
612 624
613 errorMessage = String.Empty; 625 errorMessage = String.Empty;
614 } 626 }
615 627
616 CloseArchive(errorMessage); 628 CloseArchive(errorMessage);
617 } 629 }
618 630
619 /// <summary> 631 /// <summary>
620 /// Closes the archive and notifies that we're done. 632 /// Closes the archive and notifies that we're done.
621 /// </summary> 633 /// </summary>
@@ -634,7 +646,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
634 if (errorMessage == string.Empty) 646 if (errorMessage == string.Empty)
635 errorMessage = e.Message; 647 errorMessage = e.Message;
636 } 648 }
637 649
638 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); 650 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName);
639 651
640 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); 652 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index 6a09caf..1305545 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -49,24 +49,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ArchiverModule")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ArchiverModule")]
50 public class ArchiverModule : INonSharedRegionModule, IRegionArchiverModule 50 public class ArchiverModule : INonSharedRegionModule, IRegionArchiverModule
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
55 public Scene Scene { get; private set; } 55 public Scene Scene { get; private set; }
56 public IRegionCombinerModule RegionCombinerModule { get; private set; }
57 56
58 /// <value> 57 /// <value>
59 /// The file used to load and save an opensimulator archive if no filename has been specified 58 /// The file used to load and save an opensimulator archive if no filename has been specified
60 /// </value> 59 /// </value>
61 protected const string DEFAULT_OAR_BACKUP_FILENAME = "region.oar"; 60 protected const string DEFAULT_OAR_BACKUP_FILENAME = "region.oar";
62 61
63 public string Name 62 public string Name
64 { 63 {
65 get { return "RegionArchiverModule"; } 64 get { return "RegionArchiverModule"; }
66 } 65 }
67 66
68 public Type ReplaceableInterface 67 public Type ReplaceableInterface
69 { 68 {
70 get { return null; } 69 get { return null; }
71 } 70 }
72 71
@@ -85,7 +84,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
85 84
86 public void RegionLoaded(Scene scene) 85 public void RegionLoaded(Scene scene)
87 { 86 {
88 RegionCombinerModule = scene.RequestModuleInterface<IRegionCombinerModule>();
89 } 87 }
90 88
91 public void RemoveRegion(Scene scene) 89 public void RemoveRegion(Scene scene)
@@ -110,18 +108,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
110 Vector3 displacement = new Vector3(0f, 0f, 0f); 108 Vector3 displacement = new Vector3(0f, 0f, 0f);
111 String defaultUser = ""; 109 String defaultUser = "";
112 float rotation = 0f; 110 float rotation = 0f;
113 Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0); 111 Vector3 rotationCenter = new Vector3(Scene.RegionInfo.RegionSizeX / 2f, Scene.RegionInfo.RegionSizeY / 2f, 0);
114 112 Vector3 boundingOrigin = new Vector3(0f, 0f, 0f);
113 Vector3 boundingSize = new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, float.MaxValue);
114 bool debug = false;
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);
@@ -145,12 +147,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
145 m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45"); 147 m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45");
146 return; 148 return;
147 } 149 }
148 // Convert to radians for internals 150 //pass this in as degrees now, convert to radians later during actual work phase
149 rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI; 151 rotation = Util.Clamp<float>(rotation, -359f, 359f);
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 {
157 m_log.Info("[ARCHIVER MODULE] Warning: --rotation-center no longer does anything and will be removed soon!");
154 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v); 158 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
155 } 159 }
156 catch 160 catch
@@ -160,6 +164,33 @@ namespace OpenSim.Region.CoreModules.World.Archiver
160 return; 164 return;
161 } 165 }
162 }); 166 });
167 options.Add("bounding-origin=", delegate(string v)
168 {
169 try
170 {
171 boundingOrigin = v == null ? Vector3.Zero : Vector3.Parse(v);
172 }
173 catch
174 {
175 m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube origin");
176 m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --bounding-origin \"<128,128,0>\"");
177 return;
178 }
179 });
180 options.Add("bounding-size=", delegate(string v)
181 {
182 try
183 {
184 boundingSize = v == null ? new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, float.MaxValue) : Vector3.Parse(v);
185 }
186 catch
187 {
188 m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube size");
189 m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as a positive vector3: --bounding-size \"<256,256,4096>\"");
190 return;
191 }
192 });
193 options.Add("d|debug", delegate(string v) { debug = (v != null); });
163 194
164 // Send a message to the region ready module 195 // Send a message to the region ready module
165 /* bluewall* Disable this for the time being 196 /* bluewall* Disable this for the time being
@@ -170,9 +201,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
170 rready.OarLoadingAlert("load"); 201 rready.OarLoadingAlert("load");
171 } 202 }
172 */ 203 */
173 204
174 List<string> mainParams = options.Parse(cmdparams); 205 List<string> mainParams = options.Parse(cmdparams);
175 206
176// m_log.DebugFormat("MERGE OAR IS [{0}]", mergeOar); 207// m_log.DebugFormat("MERGE OAR IS [{0}]", mergeOar);
177// 208//
178// foreach (string param in mainParams) 209// foreach (string param in mainParams)
@@ -208,6 +239,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
208 archiveOptions.Add("displacement", displacement); 239 archiveOptions.Add("displacement", displacement);
209 archiveOptions.Add("rotation", rotation); 240 archiveOptions.Add("rotation", rotation);
210 archiveOptions.Add("rotation-center", rotationCenter); 241 archiveOptions.Add("rotation-center", rotationCenter);
242 archiveOptions.Add("bounding-origin", boundingOrigin);
243 archiveOptions.Add("bounding-size", boundingSize);
244 if (debug) archiveOptions.Add("debug", null);
211 245
212 if (mainParams.Count > 2) 246 if (mainParams.Count > 2)
213 { 247 {
@@ -254,7 +288,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
254 288
255 ArchiveRegion(path, options); 289 ArchiveRegion(path, options);
256 } 290 }
257 291
258 public void ArchiveRegion(string savePath, Dictionary<string, object> options) 292 public void ArchiveRegion(string savePath, Dictionary<string, object> options)
259 { 293 {
260 ArchiveRegion(savePath, Guid.Empty, options); 294 ArchiveRegion(savePath, Guid.Empty, options);
@@ -264,7 +298,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
264 { 298 {
265 m_log.InfoFormat( 299 m_log.InfoFormat(
266 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); 300 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
267 301
268 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); 302 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options);
269 } 303 }
270 304
@@ -288,21 +322,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
288 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 322 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
289 DearchiveRegion(loadPath, Guid.Empty, archiveOptions); 323 DearchiveRegion(loadPath, Guid.Empty, archiveOptions);
290 } 324 }
291 325
292 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options) 326 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string, object> options)
293 { 327 {
294 m_log.InfoFormat( 328 m_log.InfoFormat(
295 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath); 329 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
296 330
297 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion(); 331 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion();
298 } 332 }
299 333
300 public void DearchiveRegion(Stream loadStream) 334 public void DearchiveRegion(Stream loadStream)
301 { 335 {
302 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 336 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
303 DearchiveRegion(loadStream, Guid.Empty, archiveOptions); 337 DearchiveRegion(loadStream, Guid.Empty, archiveOptions);
304 } 338 }
305
306 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options) 339 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options)
307 { 340 {
308 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion(); 341 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion();
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
index bc6a97d..0a955c5 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs
@@ -46,13 +46,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
46 /// <value> 46 /// <value>
47 /// Post a message to the log every x assets as a progress bar 47 /// Post a message to the log every x assets as a progress bar
48 /// </value> 48 /// </value>
49 protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 50; 49 protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 100;
50 50
51 /// <value> 51 /// <value>
52 /// Keep a count of the number of assets written so that we can provide status updates 52 /// Keep a count of the number of assets written so that we can provide status updates
53 /// </value> 53 /// </value>
54 protected int m_assetsWritten; 54 protected int m_assetsWritten;
55 55
56 protected TarArchiveWriter m_archiveWriter; 56 protected TarArchiveWriter m_archiveWriter;
57 57
58 public AssetsArchiver(TarArchiveWriter archiveWriter) 58 public AssetsArchiver(TarArchiveWriter archiveWriter)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
index 8c0ef88..5d3be62 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
93 93
94 StringReader sr = new StringReader(xml); 94 StringReader sr = new StringReader(xml);
95 XmlTextReader reader = new XmlTextReader(sr); 95 XmlTextReader reader = new XmlTextReader(sr);
96 reader.ProhibitDtd = true;
96 97
97 reader.ReadStartElement("assets"); 98 reader.ReadStartElement("assets");
98 reader.Read(); 99 reader.Read();
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index db66c83..91f4dc3 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -60,29 +60,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
60 Completed, 60 Completed,
61 Aborted 61 Aborted
62 }; 62 };
63
64 /// <value>
65 /// Timeout threshold if we still need assets or missing asset notifications but have stopped receiving them
66 /// from the asset service
67 /// </value>
68 protected const int TIMEOUT = 60 * 1000;
69
70 /// <value>
71 /// If a timeout does occur, limit the amount of UUID information put to the console.
72 /// </value>
73 protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3;
74
75 protected System.Timers.Timer m_requestCallbackTimer;
76 63
77 /// <value> 64 /// <value>
78 /// State of this request
79 /// </value>
80 private RequestState m_requestState = RequestState.Initial;
81
82 /// <value>
83 /// uuids to request 65 /// uuids to request
84 /// </value> 66 /// </value>
85 protected IDictionary<UUID, sbyte> m_uuids; 67 protected IDictionary<UUID, sbyte> m_uuids;
68 private int m_previousErrorsCount;
86 69
87 /// <value> 70 /// <value>
88 /// Callback used when all the assets requested have been received. 71 /// Callback used when all the assets requested have been received.
@@ -93,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
93 /// List of assets that were found. This will be passed back to the requester. 76 /// List of assets that were found. This will be passed back to the requester.
94 /// </value> 77 /// </value>
95 protected List<UUID> m_foundAssetUuids = new List<UUID>(); 78 protected List<UUID> m_foundAssetUuids = new List<UUID>();
96 79
97 /// <value> 80 /// <value>
98 /// Maintain a list of assets that could not be found. This will be passed back to the requester. 81 /// Maintain a list of assets that could not be found. This will be passed back to the requester.
99 /// </value> 82 /// </value>
@@ -104,217 +87,114 @@ namespace OpenSim.Region.CoreModules.World.Archiver
104 /// </value> 87 /// </value>
105 private int m_repliesRequired; 88 private int m_repliesRequired;
106 89
90 private System.Timers.Timer m_timeOutTimer;
91 private bool m_timeout;
92
107 /// <value> 93 /// <value>
108 /// Asset service used to request the assets 94 /// Asset service used to request the assets
109 /// </value> 95 /// </value>
110 protected IAssetService m_assetService; 96 protected IAssetService m_assetService;
111 protected IUserAccountService m_userAccountService; 97 protected IUserAccountService m_userAccountService;
112 protected UUID m_scopeID; // the grid ID 98 protected UUID m_scopeID; // the grid ID
113 99
114 protected AssetsArchiver m_assetsArchiver; 100 protected AssetsArchiver m_assetsArchiver;
115 101
116 protected Dictionary<string, object> m_options; 102 protected Dictionary<string, object> m_options;
117 103
118 protected internal AssetsRequest( 104 protected internal AssetsRequest(
119 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids, 105 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
120 IAssetService assetService, IUserAccountService userService, 106 int previousErrorsCount,
121 UUID scope, Dictionary<string, object> options, 107 IAssetService assetService, IUserAccountService userService,
108 UUID scope, Dictionary<string, object> options,
122 AssetsRequestCallback assetsRequestCallback) 109 AssetsRequestCallback assetsRequestCallback)
123 { 110 {
124 m_assetsArchiver = assetsArchiver; 111 m_assetsArchiver = assetsArchiver;
125 m_uuids = uuids; 112 m_uuids = uuids;
113 m_previousErrorsCount = previousErrorsCount;
126 m_assetsRequestCallback = assetsRequestCallback; 114 m_assetsRequestCallback = assetsRequestCallback;
127 m_assetService = assetService; 115 m_assetService = assetService;
128 m_userAccountService = userService; 116 m_userAccountService = userService;
129 m_scopeID = scope; 117 m_scopeID = scope;
130 m_options = options; 118 m_options = options;
131 m_repliesRequired = uuids.Count; 119 m_repliesRequired = uuids.Count;
132
133 // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
134 // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
135 // so we can properly abort that thread. Or request all assets synchronously, though that would be a more
136 // radical change
137 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
138 m_requestCallbackTimer.AutoReset = false;
139 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
140 } 120 }
141 121
142 protected internal void Execute() 122 protected internal void Execute()
143 { 123 {
144 m_requestState = RequestState.Running; 124 Culture.SetCurrentCulture();
145
146 m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
147
148 // We can stop here if there are no assets to fetch 125 // We can stop here if there are no assets to fetch
149 if (m_repliesRequired == 0) 126 if (m_repliesRequired == 0)
150 { 127 {
151 m_requestState = RequestState.Completed;
152 PerformAssetsRequestCallback(false); 128 PerformAssetsRequestCallback(false);
153 return; 129 return;
154 } 130 }
155 131
156 m_requestCallbackTimer.Enabled = true; 132 m_timeOutTimer = new System.Timers.Timer(60000);
133 m_timeOutTimer .AutoReset = false;
134 m_timeOutTimer.Elapsed += OnTimeout;
135 m_timeout = false;
157 136
158 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids) 137 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
159 { 138 {
160// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); 139 string thiskey = kvp.Key.ToString();
161 140 try
162// m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); 141 {
163 AssetBase asset = m_assetService.Get(kvp.Key.ToString()); 142 m_timeOutTimer.Enabled = true;
164 PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); 143 AssetBase asset = m_assetService.Get(thiskey);
165 } 144 if(m_timeout)
166 } 145 break;
146
147 m_timeOutTimer.Enabled = false;
167 148
168 protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) 149 if(asset == null)
169 { 150 {
170 bool timedOut = true; 151 m_notFoundAssetUuids.Add(new UUID(thiskey));
152 continue;
153 }
171 154
172 try 155 sbyte assetType = kvp.Value;
173 { 156 if (asset != null && assetType == (sbyte)AssetType.Unknown)
174 lock (this)
175 {
176 // Take care of the possibilty that this thread started but was paused just outside the lock before
177 // the final request came in (assuming that such a thing is possible)
178 if (m_requestState == RequestState.Completed)
179 { 157 {
180 timedOut = false; 158 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType));
181 return; 159 asset.Type = assetType;
182 } 160 }
183
184 m_requestState = RequestState.Aborted;
185 }
186 161
187 // Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure 162 m_foundAssetUuids.Add(asset.FullID);
188 // case anyway. 163 m_assetsArchiver.WriteAsset(PostProcess(asset));
189 List<UUID> uuids = new List<UUID>();
190 foreach (UUID uuid in m_uuids.Keys)
191 {
192 uuids.Add(uuid);
193 } 164 }
194 165
195 foreach (UUID uuid in m_foundAssetUuids) 166 catch (Exception e)
196 {
197 uuids.Remove(uuid);
198 }
199
200 foreach (UUID uuid in m_notFoundAssetUuids)
201 { 167 {
202 uuids.Remove(uuid); 168 m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e);
203 }
204
205 m_log.ErrorFormat(
206 "[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count);
207
208 int i = 0;
209 foreach (UUID uuid in uuids)
210 {
211 m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid);
212
213 if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT)
214 break;
215 } 169 }
216
217 if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT)
218 m_log.ErrorFormat(
219 "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT);
220
221 m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE.");
222 }
223 catch (Exception e)
224 {
225 m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace);
226 } 170 }
227 finally
228 {
229 if (timedOut)
230 WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback");
231 }
232 }
233 171
234 protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset) 172 m_timeOutTimer.Dispose();
235 { 173 int totalerrors = m_notFoundAssetUuids.Count + m_previousErrorsCount;
236 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
237 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
238 {
239 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
240 fetchedAsset.Type = (sbyte)assetType;
241 }
242 174
243 AssetRequestCallback(fetchedAssetID, this, fetchedAsset); 175 if(m_timeout)
244 } 176 m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count);
177 else if(totalerrors == 0)
178 m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count);
179 else
180 m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} of total possible assets requested were not found, were damaged or were not assets)",
181 m_foundAssetUuids.Count, totalerrors);
245 182
246 /// <summary> 183 PerformAssetsRequestCallback(m_timeout);
247 /// Called back by the asset cache when it has the asset 184 }
248 /// </summary> 185
249 /// <param name="assetID"></param> 186 private void OnTimeout(object source, ElapsedEventArgs args)
250 /// <param name="asset"></param>
251 public void AssetRequestCallback(string id, object sender, AssetBase asset)
252 { 187 {
253 Culture.SetCurrentCulture(); 188 m_timeout = true;
254
255 try
256 {
257 lock (this)
258 {
259 //m_log.DebugFormat("[ARCHIVER]: Received callback for asset {0}", id);
260
261 m_requestCallbackTimer.Stop();
262
263 if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed))
264 {
265 m_log.WarnFormat(
266 "[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.",
267 id, m_requestState);
268
269 return;
270 }
271
272 if (asset != null)
273 {
274 if (m_options.ContainsKey("verbose"))
275 m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id);
276
277 m_foundAssetUuids.Add(asset.FullID);
278
279 m_assetsArchiver.WriteAsset(PostProcess(asset));
280 }
281 else
282 {
283 if (m_options.ContainsKey("verbose"))
284 m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id);
285
286 m_notFoundAssetUuids.Add(new UUID(id));
287 }
288
289 if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired)
290 {
291 m_requestState = RequestState.Completed;
292
293 m_log.DebugFormat(
294 "[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)",
295 m_foundAssetUuids.Count, m_notFoundAssetUuids.Count);
296
297 // We want to stop using the asset cache thread asap
298 // as we now need to do the work of producing the rest of the archive
299 WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback");
300 }
301 else
302 {
303 m_requestCallbackTimer.Start();
304 }
305 }
306 }
307 catch (Exception e)
308 {
309 m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e);
310 }
311 } 189 }
312 190
313 /// <summary> 191 /// <summary>
314 /// Perform the callback on the original requester of the assets 192 /// Perform the callback on the original requester of the assets
315 /// </summary> 193 /// </summary>
316 protected void PerformAssetsRequestCallback(object o) 194 private void PerformAssetsRequestCallback(object o)
317 { 195 {
196 if(m_assetsRequestCallback == null)
197 return;
318 Culture.SetCurrentCulture(); 198 Culture.SetCurrentCulture();
319 199
320 Boolean timedOut = (Boolean)o; 200 Boolean timedOut = (Boolean)o;
@@ -330,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
330 } 210 }
331 } 211 }
332 212
333 protected AssetBase PostProcess(AssetBase asset) 213 private AssetBase PostProcess(AssetBase asset)
334 { 214 {
335 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) 215 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
336 { 216 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
index 3dcc020..809d863 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
@@ -70,6 +70,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
70 /// If null then the region doesn't have a corresponding scene, and it won't be loaded. 70 /// If null then the region doesn't have a corresponding scene, and it won't be loaded.
71 /// </summary> 71 /// </summary>
72 public Scene Scene { get; set; } 72 public Scene Scene { get; set; }
73
74 /// <summary>
75 /// The size of the region being loaded.
76 /// </summary>
77 public Vector3 RegionSize { get; set; }
78
79 public RegionInfo()
80 {
81 RegionSize = new Vector3(256f,256f,float.MaxValue);
82 }
73 } 83 }
74 84
75 /// <summary> 85 /// <summary>
@@ -113,23 +123,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver
113 public void StartRegion() 123 public void StartRegion()
114 { 124 {
115 m_curX = (m_curX == null) ? 0 : m_curX + 1; 125 m_curX = (m_curX == null) ? 0 : m_curX + 1;
116 // Note: this doesn't mean we have a real region in this location; this could just be a "hole" 126 // Note: this doesn't mean we have a real region in this location; this could just be a "hole"
117 } 127 }
118 128
119 public void SetRegionOriginalID(string id) 129 public void SetRegionOriginalID(string id)
120 { 130 {
121 m_curRegion = new RegionInfo(); 131 m_curRegion = new RegionInfo();
122 m_curRegion.Location = new Point((int)m_curX, (int)m_curY); 132 int x = (int)((m_curX == null) ? 0 : m_curX);
133 int y = (int)((m_curY == null) ? 0 : m_curY);
134
135 m_curRegion.Location = new Point(x, y);
123 m_curRegion.OriginalID = id; 136 m_curRegion.OriginalID = id;
124 // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called 137 // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
125 } 138 }
126 139
127 public void SetRegionDirectory(string directory) 140 public void SetRegionDirectory(string directory)
128 { 141 {
129 m_curRegion.Directory = directory; 142 if(m_curRegion != null)
130 m_directory2region[directory] = m_curRegion; 143 {
144 m_curRegion.Directory = directory;
145 m_directory2region[directory] = m_curRegion;
146 }
131 } 147 }
132 148
149 public void SetRegionSize(Vector3 size)
150 {
151 if(m_curRegion != null)
152 m_curRegion.RegionSize = size;
153 }
133 154
134 /// <summary> 155 /// <summary>
135 /// Sets all the scenes present in the simulator. 156 /// Sets all the scenes present in the simulator.
@@ -145,7 +166,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
145 { 166 {
146 foreach (RegionInfo archivedRegion in m_directory2region.Values) 167 foreach (RegionInfo archivedRegion in m_directory2region.Values)
147 { 168 {
148 Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY); 169 Point location = new Point((int)rootScene.RegionInfo.RegionLocX,
170 (int)rootScene.RegionInfo.RegionLocY);
171
149 location.Offset(archivedRegion.Location); 172 location.Offset(archivedRegion.Location);
150 173
151 Scene scene; 174 Scene scene;
@@ -191,7 +214,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
191 return false; 214 return false;
192 string regionDirectory = parts[1]; 215 string regionDirectory = parts[1];
193 relativePath = parts[2]; 216 relativePath = parts[2];
194 217
195 RegionInfo region; 218 RegionInfo region;
196 if (m_directory2region.TryGetValue(regionDirectory, out region)) 219 if (m_directory2region.TryGetValue(regionDirectory, out region))
197 { 220 {
@@ -228,5 +251,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
228 return m_newId2region.Keys.ToList(); 251 return m_newId2region.Keys.ToList();
229 } 252 }
230 253
254 public int GetScenesCount()
255 {
256 return m_directory2region.Count;
257 }
231 } 258 }
232} 259}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 9f197f5..6885299 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -65,7 +65,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
65 protected SerialiserModule m_serialiserModule; 65 protected SerialiserModule m_serialiserModule;
66 66
67 protected TaskInventoryItem m_soundItem; 67 protected TaskInventoryItem m_soundItem;
68 68
69 private AutoResetEvent m_oarEvent = new AutoResetEvent(false);
70
69 [SetUp] 71 [SetUp]
70 public override void SetUp() 72 public override void SetUp()
71 { 73 {
@@ -87,11 +89,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
87 m_lastRequestId = requestId; 89 m_lastRequestId = requestId;
88 m_lastErrorMessage = errorMessage; 90 m_lastErrorMessage = errorMessage;
89 Console.WriteLine("About to pulse ArchiverTests on LoadCompleted"); 91 Console.WriteLine("About to pulse ArchiverTests on LoadCompleted");
90 92 m_oarEvent.Set();
91 Monitor.PulseAll(this);
92 } 93 }
93 } 94 }
94 95
95 private void SaveCompleted(Guid requestId, string errorMessage) 96 private void SaveCompleted(Guid requestId, string errorMessage)
96 { 97 {
97 lock (this) 98 lock (this)
@@ -99,7 +100,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
99 m_lastRequestId = requestId; 100 m_lastRequestId = requestId;
100 m_lastErrorMessage = errorMessage; 101 m_lastErrorMessage = errorMessage;
101 Console.WriteLine("About to pulse ArchiverTests on SaveCompleted"); 102 Console.WriteLine("About to pulse ArchiverTests on SaveCompleted");
102 Monitor.PulseAll(this); 103 m_oarEvent.Set();
103 } 104 }
104 } 105 }
105 106
@@ -110,6 +111,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
110 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); 111 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
111 Vector3 groupPosition = new Vector3(10, 20, 30); 112 Vector3 groupPosition = new Vector3(10, 20, 30);
112 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); 113 Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
114 rotationOffset.Normalize();
113// Vector3 offsetPosition = new Vector3(5, 10, 15); 115// Vector3 offsetPosition = new Vector3(5, 10, 15);
114 116
115 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, Vector3.Zero) { Name = partName }; 117 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, Vector3.Zero) { Name = partName };
@@ -122,11 +124,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
122 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); 124 PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder();
123 Vector3 groupPosition = new Vector3(90, 80, 70); 125 Vector3 groupPosition = new Vector3(90, 80, 70);
124 Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); 126 Quaternion rotationOffset = new Quaternion(60, 70, 80, 90);
127 rotationOffset.Normalize();
125 Vector3 offsetPosition = new Vector3(20, 25, 30); 128 Vector3 offsetPosition = new Vector3(20, 25, 30);
126 129
127 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; 130 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
128 } 131 }
129 132
130 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) 133 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
131 { 134 {
132 SceneObjectPart part1 = CreateSceneObjectPart1(); 135 SceneObjectPart part1 = CreateSceneObjectPart1();
@@ -192,17 +195,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
192 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 195 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
193 196
194 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); 197 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
195 198
196 lock (this) 199 m_oarEvent.Reset();
197 { 200 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId);
198 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId); 201 //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer;
199 //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; 202 //while (assetServer.HasWaitingRequests())
200 //while (assetServer.HasWaitingRequests()) 203 // assetServer.ProcessNextRequest();
201 // assetServer.ProcessNextRequest(); 204
202 205 m_oarEvent.WaitOne(60000);
203 Monitor.Wait(this, 60000); 206
204 }
205
206 Assert.That(m_lastRequestId, Is.EqualTo(requestId)); 207 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
207 208
208 byte[] archive = archiveWriteStream.ToArray(); 209 byte[] archive = archiveWriteStream.ToArray();
@@ -210,7 +211,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
210 TarArchiveReader tar = new TarArchiveReader(archiveReadStream); 211 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
211 212
212 bool gotNcAssetFile = false; 213 bool gotNcAssetFile = false;
213 214
214 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt"); 215 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt");
215 216
216 List<string> foundPaths = new List<string>(); 217 List<string> foundPaths = new List<string>();
@@ -219,7 +220,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
219 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); 220 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
220 221
221 string filePath; 222 string filePath;
222 TarArchiveReader.TarEntryType tarEntryType; 223 TarArchiveReader.TarEntryType tarEntryType;
223 224
224 byte[] data = tar.ReadEntry(out filePath, out tarEntryType); 225 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
225 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 226 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
@@ -227,9 +228,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
227 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 228 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
228 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); 229 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
229 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 230 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
230 231
231 Assert.That(arr.ControlFileLoaded, Is.True); 232 Assert.That(arr.ControlFileLoaded, Is.True);
232 233
233 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 234 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
234 { 235 {
235 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) 236 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
@@ -265,7 +266,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
265 m_scene.AddNewSceneObject(sog1, false); 266 m_scene.AddNewSceneObject(sog1, false);
266 267
267 SceneObjectPart part2 = CreateSceneObjectPart2(); 268 SceneObjectPart part2 = CreateSceneObjectPart2();
268 269
269 AssetNotecard nc = new AssetNotecard(); 270 AssetNotecard nc = new AssetNotecard();
270 nc.BodyText = "Hello World!"; 271 nc.BodyText = "Hello World!";
271 nc.Encode(); 272 nc.Encode();
@@ -275,10 +276,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
275 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); 276 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
276 m_scene.AssetService.Store(ncAsset); 277 m_scene.AssetService.Store(ncAsset);
277 SceneObjectGroup sog2 = new SceneObjectGroup(part2); 278 SceneObjectGroup sog2 = new SceneObjectGroup(part2);
278 TaskInventoryItem ncItem 279 TaskInventoryItem ncItem
279 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; 280 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
280 part2.Inventory.AddInventoryItem(ncItem, true); 281 part2.Inventory.AddInventoryItem(ncItem, true);
281 282
282 m_scene.AddNewSceneObject(sog2, false); 283 m_scene.AddNewSceneObject(sog2, false);
283 284
284 MemoryStream archiveWriteStream = new MemoryStream(); 285 MemoryStream archiveWriteStream = new MemoryStream();
@@ -287,6 +288,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
287 288
288 Dictionary<string, Object> options = new Dictionary<string, Object>(); 289 Dictionary<string, Object> options = new Dictionary<string, Object>();
289 options.Add("noassets", true); 290 options.Add("noassets", true);
291
290 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); 292 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
291 293
292 // Don't wait for completion - with --noassets save oar happens synchronously 294 // Don't wait for completion - with --noassets save oar happens synchronously
@@ -304,7 +306,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
304 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); 306 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
305 307
306 string filePath; 308 string filePath;
307 TarArchiveReader.TarEntryType tarEntryType; 309 TarArchiveReader.TarEntryType tarEntryType;
308 310
309 byte[] data = tar.ReadEntry(out filePath, out tarEntryType); 311 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
310 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 312 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
@@ -312,9 +314,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
312 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 314 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
313 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); 315 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions);
314 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 316 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
315 317
316 Assert.That(arr.ControlFileLoaded, Is.True); 318 Assert.That(arr.ControlFileLoaded, Is.True);
317 319
318 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 320 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
319 { 321 {
320 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) 322 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
@@ -343,11 +345,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
343 345
344 MemoryStream archiveWriteStream = new MemoryStream(); 346 MemoryStream archiveWriteStream = new MemoryStream();
345 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); 347 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
346 348
347 // Put in a random blank directory to check that this doesn't upset the load process 349 // Put in a random blank directory to check that this doesn't upset the load process
348 tar.WriteDir("ignoreme"); 350 tar.WriteDir("ignoreme");
349 351
350 // Also check that direct entries which will also have a file entry containing that directory doesn't 352 // Also check that direct entries which will also have a file entry containing that directory doesn't
351 // upset load 353 // upset load
352 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 354 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
353 355
@@ -390,17 +392,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
390 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), 392 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
391 part1.UUID); 393 part1.UUID);
392 tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1)); 394 tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1));
393 395
394 tar.Close(); 396 tar.Close();
395 397
396 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 398 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
397 399
398 lock (this) 400 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
399 { 401 m_oarEvent.Reset();
400 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 402 m_archiverModule.DearchiveRegion(archiveReadStream);
401 m_archiverModule.DearchiveRegion(archiveReadStream); 403
402 } 404 m_oarEvent.WaitOne(60000);
403 405
404 Assert.That(m_lastErrorMessage, Is.Null); 406 Assert.That(m_lastErrorMessage, Is.Null);
405 407
406 TestLoadedRegion(part1, soundItemName, soundData); 408 TestLoadedRegion(part1, soundItemName, soundData);
@@ -444,11 +446,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
444 446
445 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 447 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
446 448
447 lock (this) 449 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
448 { 450 m_oarEvent.Reset();
449 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 451 m_archiverModule.DearchiveRegion(archiveReadStream);
450 m_archiverModule.DearchiveRegion(archiveReadStream); 452
451 } 453 m_oarEvent.WaitOne(60000);
452 454
453 Assert.That(m_lastErrorMessage, Is.Null); 455 Assert.That(m_lastErrorMessage, Is.Null);
454 456
@@ -473,35 +475,33 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
473 m_scene.AddNewSceneObject(sog1, false); 475 m_scene.AddNewSceneObject(sog1, false);
474 476
475 SceneObjectPart part2 = CreateSceneObjectPart2(); 477 SceneObjectPart part2 = CreateSceneObjectPart2();
476 478
477 AssetNotecard nc = new AssetNotecard(); 479 AssetNotecard nc = new AssetNotecard();
478 nc.BodyText = "Hello World!"; 480 nc.BodyText = "Hello World!";
479 nc.Encode(); 481 nc.Encode();
480 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); 482 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
481 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); 483 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
482 AssetBase ncAsset 484 AssetBase ncAsset
483 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); 485 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
484 m_scene.AssetService.Store(ncAsset); 486 m_scene.AssetService.Store(ncAsset);
485 SceneObjectGroup sog2 = new SceneObjectGroup(part2); 487 SceneObjectGroup sog2 = new SceneObjectGroup(part2);
486 TaskInventoryItem ncItem 488 TaskInventoryItem ncItem
487 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; 489 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
488 part2.Inventory.AddInventoryItem(ncItem, true); 490 part2.Inventory.AddInventoryItem(ncItem, true);
489 491
490 m_scene.AddNewSceneObject(sog2, false); 492 m_scene.AddNewSceneObject(sog2, false);
491 493
492 MemoryStream archiveWriteStream = new MemoryStream(); 494 MemoryStream archiveWriteStream = new MemoryStream();
493 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 495 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
494 496
495 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); 497 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
496 498
497 lock (this) 499 m_oarEvent.Reset();
498 { 500 m_archiverModule.ArchiveRegion(
499 m_archiverModule.ArchiveRegion(
500 archiveWriteStream, requestId, new Dictionary<string, Object>() { { "wipe-owners", Boolean.TrueString } }); 501 archiveWriteStream, requestId, new Dictionary<string, Object>() { { "wipe-owners", Boolean.TrueString } });
501 502
502 Monitor.Wait(this, 60000); 503 m_oarEvent.WaitOne(60000);
503 } 504
504
505 Assert.That(m_lastRequestId, Is.EqualTo(requestId)); 505 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
506 506
507 byte[] archive = archiveWriteStream.ToArray(); 507 byte[] archive = archiveWriteStream.ToArray();
@@ -526,11 +526,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
526 526
527 scene2.RegionInfo.EstateSettings.EstateOwner = estateOwner; 527 scene2.RegionInfo.EstateSettings.EstateOwner = estateOwner;
528 528
529 lock (this) 529 scene2.EventManager.OnOarFileLoaded += LoadCompleted;
530 { 530 m_oarEvent.Reset();
531 scene2.EventManager.OnOarFileLoaded += LoadCompleted; 531 archiverModule.DearchiveRegion(archiveReadStream);
532 archiverModule.DearchiveRegion(archiveReadStream); 532
533 } 533 m_oarEvent.WaitOne(60000);
534 534
535 Assert.That(m_lastErrorMessage, Is.Null); 535 Assert.That(m_lastErrorMessage, Is.Null);
536 536
@@ -557,16 +557,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
557 MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector(); 557 MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector();
558 558
559 IConfigSource configSource = new IniConfigSource(); 559 IConfigSource configSource = new IniConfigSource();
560 IConfig config = configSource.AddConfig("Groups"); 560 IConfig config = configSource.AddConfig("Groups");
561 config.Set("Enabled", true); 561 config.Set("Enabled", true);
562 config.Set("Module", "GroupsModule"); 562 config.Set("Module", "GroupsModule");
563 config.Set("DebugEnabled", true); 563 config.Set("DebugEnabled", true);
564 SceneHelpers.SetupSceneModules( 564 SceneHelpers.SetupSceneModules(
565 m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() }); 565 m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() });
566 566
567 // Create group in scene for loading 567 // Create group in scene for loading
568 // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests. 568 // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests.
569 UUID groupID 569 UUID groupID
570 = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero); 570 = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero);
571 571
572 // Construct OAR 572 // Construct OAR
@@ -591,11 +591,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
591 oarStream = new MemoryStream(oarStream.ToArray()); 591 oarStream = new MemoryStream(oarStream.ToArray());
592 592
593 // Load OAR 593 // Load OAR
594 lock (this) 594 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
595 { 595 m_oarEvent.Reset();
596 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 596 m_archiverModule.DearchiveRegion(oarStream);
597 m_archiverModule.DearchiveRegion(oarStream); 597
598 } 598 m_oarEvent.WaitOne(60000);
599 599
600 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16); 600 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16);
601 LandData rLd = rLo.LandData; 601 LandData rLd = rLo.LandData;
@@ -617,7 +617,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
617 617
618 MemoryStream archiveWriteStream = new MemoryStream(); 618 MemoryStream archiveWriteStream = new MemoryStream();
619 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); 619 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
620 620
621 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 621 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
622 tar.WriteFile( 622 tar.WriteFile(
623 ArchiveConstants.CONTROL_FILE_PATH, 623 ArchiveConstants.CONTROL_FILE_PATH,
@@ -658,17 +658,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
658 rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33")); 658 rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33"));
659 659
660 tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs)); 660 tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs));
661 661
662 tar.Close(); 662 tar.Close();
663 663
664 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 664 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
665 665
666 lock (this) 666 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
667 { 667 m_oarEvent.Reset();
668 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 668 m_archiverModule.DearchiveRegion(archiveReadStream);
669 m_archiverModule.DearchiveRegion(archiveReadStream); 669
670 } 670 m_oarEvent.WaitOne(60000);
671 671
672 Assert.That(m_lastErrorMessage, Is.Null); 672 Assert.That(m_lastErrorMessage, Is.Null);
673 RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings; 673 RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings;
674 674
@@ -705,7 +705,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
705 Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID 705 Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID
706 Assert.AreEqual(0, loadedRs.SpawnPoints().Count); 706 Assert.AreEqual(0, loadedRs.SpawnPoints().Count);
707 } 707 }
708 708
709 /// <summary> 709 /// <summary>
710 /// Test merging an OpenSim Region Archive into an existing scene 710 /// Test merging an OpenSim Region Archive into an existing scene
711 /// </summary> 711 /// </summary>
@@ -737,13 +737,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
737 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); 737 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
738 738
739 // Write out this scene 739 // Write out this scene
740
740 scene.EventManager.OnOarFileSaved += SaveCompleted; 741 scene.EventManager.OnOarFileSaved += SaveCompleted;
742 m_oarEvent.Reset();
743 m_archiverModule.ArchiveRegion(archiveWriteStream);
741 744
742 lock (this) 745 m_oarEvent.WaitOne(60000);
743 {
744 m_archiverModule.ArchiveRegion(archiveWriteStream);
745 Monitor.Wait(this, 60000);
746 }
747 } 746 }
748 747
749 { 748 {
@@ -754,10 +753,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
754 byte[] archive = archiveWriteStream.ToArray(); 753 byte[] archive = archiveWriteStream.ToArray();
755 MemoryStream archiveReadStream = new MemoryStream(archive); 754 MemoryStream archiveReadStream = new MemoryStream(archive);
756 755
756 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
757 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 757 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
758 archiveOptions.Add("merge", null); 758 archiveOptions.Add("merge", null);
759 m_oarEvent.Reset();
759 m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions); 760 m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions);
760 761
762 m_oarEvent.WaitOne(60000);
763
761 SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name); 764 SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
762 Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); 765 Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
763 Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge"); 766 Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge");
@@ -816,7 +819,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
816 SceneObjectGroup sog1; 819 SceneObjectGroup sog1;
817 SceneObjectGroup sog2; 820 SceneObjectGroup sog2;
818 UUID ncAssetUuid; 821 UUID ncAssetUuid;
819 822
820 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid); 823 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
821 824
822 expectedPaths[scene.RegionInfo.RegionID] = new List<string>(); 825 expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
@@ -829,18 +832,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
829 832
830 // Save OAR 833 // Save OAR
831 MemoryStream archiveWriteStream = new MemoryStream(); 834 MemoryStream archiveWriteStream = new MemoryStream();
832 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
833 835
834 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); 836 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
835 837
836 Dictionary<string, Object> options = new Dictionary<string, Object>(); 838 Dictionary<string, Object> options = new Dictionary<string, Object>();
837 options.Add("all", true); 839 options.Add("all", true);
838 840
839 lock (this) 841 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
840 { 842 m_oarEvent.Reset();
841 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); 843 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
842 Monitor.Wait(this, 60000); 844
843 } 845 m_oarEvent.WaitOne(60000);
844 846
845 847
846 // Check that the OAR contains the expected data 848 // Check that the OAR contains the expected data
@@ -991,7 +993,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
991 993
992 tar.Close(); 994 tar.Close();
993 995
994 996
995 // Delete the current objects, to test that they're loaded from the OAR and didn't 997 // Delete the current objects, to test that they're loaded from the OAR and didn't
996 // just remain in the scene. 998 // just remain in the scene.
997 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene) 999 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
@@ -1007,11 +1009,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
1007 1009
1008 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 1010 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
1009 1011
1010 lock (this) 1012 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
1011 { 1013 m_oarEvent.Reset();
1012 m_scene.EventManager.OnOarFileLoaded += LoadCompleted; 1014 m_archiverModule.DearchiveRegion(archiveReadStream);
1013 m_archiverModule.DearchiveRegion(archiveReadStream); 1015
1014 } 1016 m_oarEvent.WaitOne(60000);
1015 1017
1016 Assert.That(m_lastErrorMessage, Is.Null); 1018 Assert.That(m_lastErrorMessage, Is.Null);
1017 1019
@@ -1027,8 +1029,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
1027 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 1029 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
1028 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); 1030 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
1029 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); 1031 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
1030 Assert.That( 1032
1031 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); 1033 Quaternion qtmp1 = new Quaternion (
1034 (float)Math.Round(object1PartLoaded.RotationOffset.X,5),
1035 (float)Math.Round(object1PartLoaded.RotationOffset.Y,5),
1036 (float)Math.Round(object1PartLoaded.RotationOffset.Z,5),
1037 (float)Math.Round(object1PartLoaded.RotationOffset.W,5));
1038 Quaternion qtmp2 = new Quaternion (
1039 (float)Math.Round(part1.RotationOffset.X,5),
1040 (float)Math.Round(part1.RotationOffset.Y,5),
1041 (float)Math.Round(part1.RotationOffset.Z,5),
1042 (float)Math.Round(part1.RotationOffset.W,5));
1043
1044 Assert.That(qtmp1, Is.EqualTo(qtmp2), "object1 rotation offset not equal");
1032 Assert.That( 1045 Assert.That(
1033 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); 1046 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
1034 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); 1047 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
diff --git a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
index d217f36..a450dd6 100644
--- a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
+++ b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading;
30using Mono.Addins; 31using Mono.Addins;
31using Nini.Config; 32using Nini.Config;
32using OpenMetaverse; 33using OpenMetaverse;
@@ -39,16 +40,20 @@ namespace OpenSim.Region.CoreModules.World
39 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CloudModule")] 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CloudModule")]
40 public class CloudModule : ICloudModule, INonSharedRegionModule 41 public class CloudModule : ICloudModule, INonSharedRegionModule
41 { 42 {
42// private static readonly log4net.ILog m_log 43// private static readonly log4net.ILog m_log
43// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 44// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
44 private uint m_frame = 0; 45 private uint m_frame = 0;
45 private int m_frameUpdateRate = 1000; 46 private int m_frameUpdateRate = 1000;
46 private Random m_rndnums = new Random(Environment.TickCount); 47 private Random m_rndnums;
47 private Scene m_scene = null; 48 private Scene m_scene = null;
48 private bool m_ready = false; 49 private bool m_ready = false;
49 private bool m_enabled = false; 50 private bool m_enabled = false;
50 private float m_cloudDensity = 1.0F; 51 private float m_cloudDensity = 1.0F;
51 private float[] cloudCover = new float[16 * 16]; 52 private float[] cloudCover = new float[16 * 16];
53 private int m_dataVersion;
54 private bool m_busy;
55 private object cloudlock = new object();
56
52 57
53 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
54 { 59 {
@@ -70,11 +75,17 @@ namespace OpenSim.Region.CoreModules.World
70 75
71 m_scene = scene; 76 m_scene = scene;
72 77
73 scene.EventManager.OnNewClient += CloudsToClient;
74 scene.RegisterModuleInterface<ICloudModule>(this); 78 scene.RegisterModuleInterface<ICloudModule>(this);
75 scene.EventManager.OnFrame += CloudUpdate; 79 int seed = Environment.TickCount;
80 seed += (int)(scene.RegionInfo.RegionLocX << 16);
81 seed += (int)(scene.RegionInfo.RegionLocY);
82 m_rndnums = new Random(seed);
76 83
77 GenerateCloudCover(); 84 GenerateCloudCover();
85 m_dataVersion = (int)m_scene.AllocateLocalId();
86
87 scene.EventManager.OnNewClient += CloudsToClient;
88 scene.EventManager.OnFrame += CloudUpdate;
78 89
79 m_ready = true; 90 m_ready = true;
80 } 91 }
@@ -89,7 +100,6 @@ namespace OpenSim.Region.CoreModules.World
89 m_scene.EventManager.OnNewClient -= CloudsToClient; 100 m_scene.EventManager.OnNewClient -= CloudsToClient;
90 m_scene.EventManager.OnFrame -= CloudUpdate; 101 m_scene.EventManager.OnFrame -= CloudUpdate;
91 m_scene.UnregisterModuleInterface<ICloudModule>(this); 102 m_scene.UnregisterModuleInterface<ICloudModule>(this);
92
93 m_scene = null; 103 m_scene = null;
94 } 104 }
95 105
@@ -127,7 +137,8 @@ namespace OpenSim.Region.CoreModules.World
127 137
128 if (cloudCover != null) 138 if (cloudCover != null)
129 { 139 {
130 cover = cloudCover[y * 16 + x]; 140 lock(cloudlock)
141 cover = cloudCover[y * 16 + x];
131 } 142 }
132 143
133 return cover; 144 return cover;
@@ -152,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World
152 columnRight = 0; 163 columnRight = 0;
153 columnLeft = x - 1; 164 columnLeft = x - 1;
154 } 165 }
155 else 166 else
156 { 167 {
157 columnRight = x + 1; 168 columnRight = x + 1;
158 columnLeft = x - 1; 169 columnLeft = x - 1;
@@ -174,40 +185,65 @@ namespace OpenSim.Region.CoreModules.World
174 rowAbove = y + 1; 185 rowAbove = y + 1;
175 rowBelow = y - 1; 186 rowBelow = y - 1;
176 } 187 }
177 float neighborAverage = (cloudCover[rowBelow * 16 + columnLeft] + 188 float neighborAverage = (cloudCover[rowBelow * 16 + columnLeft] +
178 cloudCover[y * 16 + columnLeft] + 189 cloudCover[y * 16 + columnLeft] +
179 cloudCover[rowAbove * 16 + columnLeft] + 190 cloudCover[rowAbove * 16 + columnLeft] +
180 cloudCover[rowBelow * 16 + x] + 191 cloudCover[rowBelow * 16 + x] +
181 cloudCover[rowAbove * 16 + x] + 192 cloudCover[rowAbove * 16 + x] +
182 cloudCover[rowBelow * 16 + columnRight] + 193 cloudCover[rowBelow * 16 + columnRight] +
183 cloudCover[y * 16 + columnRight] + 194 cloudCover[y * 16 + columnRight] +
184 cloudCover[rowAbove * 16 + columnRight] + 195 cloudCover[rowAbove * 16 + columnRight] +
185 cloudCover[y * 16 + x]) / 9; 196 cloudCover[y * 16 + x]) / 9;
186 newCover[y * 16 + x] = ((neighborAverage / m_cloudDensity) + 0.175f) % 1.0f; 197 newCover[y * 16 + x] = ((neighborAverage / m_cloudDensity) + 0.175f) % 1.0f;
187 newCover[y * 16 + x] *= m_cloudDensity; 198 newCover[y * 16 + x] *= m_cloudDensity;
188 } 199 }
189 } 200 }
190 Array.Copy(newCover, cloudCover, 16 * 16); 201 Array.Copy(newCover, cloudCover, 16 * 16);
202 m_dataVersion++;
191 } 203 }
192 204
193 private void CloudUpdate() 205 private void CloudUpdate()
194 { 206 {
195 if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready || (m_cloudDensity == 0)) 207 if ((!m_ready || m_busy || m_cloudDensity == 0 ||
196 { 208 (m_frame++ % m_frameUpdateRate) != 0))
197 return; 209 return;
198 } 210
199 UpdateCloudCover(); 211 if(Monitor.TryEnter(cloudlock))
212 {
213 m_busy = true;
214 Util.FireAndForget(delegate
215 {
216 try
217 {
218 lock(cloudlock)
219 {
220 UpdateCloudCover();
221 m_scene.ForEachClient(delegate(IClientAPI client)
222 {
223 client.SendCloudData(m_dataVersion, cloudCover);
224 });
225 }
226 }
227 finally
228 {
229 m_busy = false;
230 }
231 },
232 null, "CloudModuleUpdate");
233 Monitor.Exit(cloudlock);
234 }
200 } 235 }
201 236
202 public void CloudsToClient(IClientAPI client) 237 public void CloudsToClient(IClientAPI client)
203 { 238 {
204 if (m_ready) 239 if (m_ready)
205 { 240 {
206 client.SendCloudData(cloudCover); 241 lock(cloudlock)
242 client.SendCloudData(m_dataVersion, cloudCover);
207 } 243 }
208 } 244 }
209 245
210 246
211 /// <summary> 247 /// <summary>
212 /// Calculate the cloud cover over the region. 248 /// Calculate the cloud cover over the region.
213 /// </summary> 249 /// </summary>
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs b/OpenSim/Region/CoreModules/World/Estate/EstateConnector.cs
index 73e706c..8001c3c 100644
--- a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateConnector.cs
@@ -45,17 +45,22 @@ namespace OpenSim.Region.CoreModules.World.Estate
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 protected XEstateModule m_EstateModule; 48 protected EstateModule m_EstateModule;
49 private string token;
50 uint port = 0;
49 51
50 public EstateConnector(XEstateModule module) 52 public EstateConnector(EstateModule module, string _token, uint _port)
51 { 53 {
52 m_EstateModule = module; 54 m_EstateModule = module;
55 token = _token;
56 port = _port;
53 } 57 }
54 58
55 public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID) 59 public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID)
56 { 60 {
57 Dictionary<string, object> sendData = new Dictionary<string, object>(); 61 Dictionary<string, object> sendData = new Dictionary<string, object>();
58 sendData["METHOD"] = "teleport_home_one_user"; 62 sendData["METHOD"] = "teleport_home_one_user";
63 sendData["TOKEN"] = token;
59 64
60 sendData["EstateID"] = EstateID.ToString(); 65 sendData["EstateID"] = EstateID.ToString();
61 sendData["PreyID"] = PreyID.ToString(); 66 sendData["PreyID"] = PreyID.ToString();
@@ -67,6 +72,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
67 { 72 {
68 Dictionary<string, object> sendData = new Dictionary<string, object>(); 73 Dictionary<string, object> sendData = new Dictionary<string, object>();
69 sendData["METHOD"] = "teleport_home_all_users"; 74 sendData["METHOD"] = "teleport_home_all_users";
75 sendData["TOKEN"] = token;
70 76
71 sendData["EstateID"] = EstateID.ToString(); 77 sendData["EstateID"] = EstateID.ToString();
72 78
@@ -77,6 +83,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
77 { 83 {
78 Dictionary<string, object> sendData = new Dictionary<string, object>(); 84 Dictionary<string, object> sendData = new Dictionary<string, object>();
79 sendData["METHOD"] = "update_covenant"; 85 sendData["METHOD"] = "update_covenant";
86 sendData["TOKEN"] = token;
80 87
81 sendData["CovenantID"] = CovenantID.ToString(); 88 sendData["CovenantID"] = CovenantID.ToString();
82 sendData["EstateID"] = EstateID.ToString(); 89 sendData["EstateID"] = EstateID.ToString();
@@ -99,6 +106,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
99 { 106 {
100 Dictionary<string, object> sendData = new Dictionary<string, object>(); 107 Dictionary<string, object> sendData = new Dictionary<string, object>();
101 sendData["METHOD"] = "update_estate"; 108 sendData["METHOD"] = "update_estate";
109 sendData["TOKEN"] = token;
102 110
103 sendData["EstateID"] = EstateID.ToString(); 111 sendData["EstateID"] = EstateID.ToString();
104 112
@@ -119,6 +127,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
119 { 127 {
120 Dictionary<string, object> sendData = new Dictionary<string, object>(); 128 Dictionary<string, object> sendData = new Dictionary<string, object>();
121 sendData["METHOD"] = "estate_message"; 129 sendData["METHOD"] = "estate_message";
130 sendData["TOKEN"] = token;
122 131
123 sendData["EstateID"] = EstateID.ToString(); 132 sendData["EstateID"] = EstateID.ToString();
124 sendData["FromID"] = FromID.ToString(); 133 sendData["FromID"] = FromID.ToString();
@@ -132,47 +141,43 @@ namespace OpenSim.Region.CoreModules.World.Estate
132 { 141 {
133 List<UUID> regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID); 142 List<UUID> regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID);
134 143
135 UUID ScopeID = UUID.Zero; 144 // Don't send to the same instance twice
145 List<string> done = new List<string>();
136 146
137 // Handle local regions locally 147 // Handle local regions locally
138 //
139 lock (m_EstateModule.Scenes) 148 lock (m_EstateModule.Scenes)
140 { 149 {
141 foreach (Scene s in m_EstateModule.Scenes) 150 foreach (Scene s in m_EstateModule.Scenes)
142 { 151 {
143 if (regions.Contains(s.RegionInfo.RegionID)) 152 RegionInfo sreg = s.RegionInfo;
153 if (regions.Contains(sreg.RegionID))
144 { 154 {
145 // All regions in one estate are in the same scope. 155 string url = sreg.ExternalHostName + ":" + sreg.HttpPort;
146 // Use that scope. 156 regions.Remove(sreg.RegionID);
147 // 157 if(!done.Contains(url)) // we may have older regs with same url lost in dbs
148 ScopeID = s.RegionInfo.ScopeID; 158 done.Add(url);
149 regions.Remove(s.RegionInfo.RegionID);
150 } 159 }
151 } 160 }
152 } 161 }
153 162
154 // Our own region should always be in the above list. 163 if(regions.Count == 0)
155 // In a standalone this would not be true. But then, 164 return;
156 // Scope ID is not relevat there. Use first scope.
157 //
158 if (ScopeID == UUID.Zero)
159 ScopeID = m_EstateModule.Scenes[0].RegionInfo.ScopeID;
160 165
161 // Don't send to the same instance twice 166 Scene baseScene = m_EstateModule.Scenes[0];
162 // 167 UUID ScopeID = baseScene.RegionInfo.ScopeID;
163 List<string> done = new List<string>(); 168 IGridService gridService = baseScene.GridService;
169 if(gridService == null)
170 return;
164 171
165 // Send to remote regions 172 // Send to remote regions
166 //
167 foreach (UUID regionID in regions) 173 foreach (UUID regionID in regions)
168 { 174 {
169 GridRegion region = m_EstateModule.Scenes[0].GridService.GetRegionByUUID(ScopeID, regionID); 175 GridRegion region = gridService.GetRegionByUUID(ScopeID, regionID);
170 if (region != null) 176 if (region != null)
171 { 177 {
172 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; 178 string url = region.ExternalHostName + ":" + region.HttpPort;
173 if (done.Contains(url)) 179 if(done.Contains(url))
174 continue; 180 continue;
175
176 Call(region, sendData); 181 Call(region, sendData);
177 done.Add(url); 182 done.Add(url);
178 } 183 }
@@ -185,9 +190,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
185 // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString); 190 // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString);
186 try 191 try
187 { 192 {
188 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; 193 string url = "";
194 if(port != 0)
195 url = "http://" + region.ExternalHostName + ":" + port + "/";
196 else
197 url = region.ServerURI;
198
189 string reply = SynchronousRestFormsRequester.MakeRequest("POST", 199 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
190 url + "/estate", 200 url + "estate",
191 reqString); 201 reqString);
192 if (reply != string.Empty) 202 if (reply != string.Empty)
193 { 203 {
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index 702b503..7879f83 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -49,18 +49,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
49 public class EstateManagementCommands 49 public class EstateManagementCommands
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 protected EstateManagementModule m_module; 53 protected EstateManagementModule m_module;
54 54
55 public EstateManagementCommands(EstateManagementModule module) 55 public EstateManagementCommands(EstateManagementModule module)
56 { 56 {
57 m_module = module; 57 m_module = module;
58 } 58 }
59 59
60 public void Initialise() 60 public void Initialise()
61 { 61 {
62// m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName); 62// m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName);
63 63
64 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture", 64 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture",
65 "set terrain texture <number> <uuid> [<x>] [<y>]", 65 "set terrain texture <number> <uuid> [<x>] [<y>]",
66 "Sets the terrain <number> to <uuid>, if <x> or <y> are specified, it will only " + 66 "Sets the terrain <number> to <uuid>, if <x> or <y> are specified, it will only " +
@@ -77,14 +77,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
77 77
78 m_module.Scene.AddCommand("Regions", m_module, "set water height", 78 m_module.Scene.AddCommand("Regions", m_module, "set water height",
79 "set water height <height> [<x>] [<y>]", 79 "set water height <height> [<x>] [<y>]",
80 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " + 80 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " +
81 "Specify -1 in <x> or <y> to wildcard that coordinate.", 81 "Specify -1 in <x> or <y> to wildcard that coordinate.",
82 consoleSetWaterHeight); 82 consoleSetWaterHeight);
83 83
84 m_module.Scene.AddCommand( 84 m_module.Scene.AddCommand(
85 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand); 85 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
86 } 86 }
87 87
88 public void Close() {} 88 public void Close() {}
89 89
90 #region CommandHandlers 90 #region CommandHandlers
@@ -120,7 +120,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
120 m_module.Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; 120 m_module.Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture;
121 break; 121 break;
122 } 122 }
123 123
124 m_module.Scene.RegionInfo.RegionSettings.Save(); 124 m_module.Scene.RegionInfo.RegionSettings.Save();
125 m_module.TriggerRegionInfoChange(); 125 m_module.TriggerRegionInfoChange();
126 m_module.sendRegionHandshakeToAll(); 126 m_module.sendRegionHandshakeToAll();
@@ -130,7 +130,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
130 protected void consoleSetWaterHeight(string module, string[] args) 130 protected void consoleSetWaterHeight(string module, string[] args)
131 { 131 {
132 string heightstring = args[3]; 132 string heightstring = args[3];
133 133
134 int x = (args.Length > 4 ? int.Parse(args[4]) : -1); 134 int x = (args.Length > 4 ? int.Parse(args[4]) : -1);
135 int y = (args.Length > 5 ? int.Parse(args[5]) : -1); 135 int y = (args.Length > 5 ? int.Parse(args[5]) : -1);
136 136
@@ -143,13 +143,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
143 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " + 143 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " +
144 string.Format(" {0}", selectedheight)); 144 string.Format(" {0}", selectedheight));
145 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight; 145 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight;
146 146
147 m_module.Scene.RegionInfo.RegionSettings.Save(); 147 m_module.Scene.RegionInfo.RegionSettings.Save();
148 m_module.TriggerRegionInfoChange(); 148 m_module.TriggerRegionInfoChange();
149 m_module.sendRegionHandshakeToAll(); 149 m_module.sendRegionHandshakeToAll();
150 } 150 }
151 } 151 }
152 } 152 }
153 protected void consoleSetTerrainHeights(string module, string[] args) 153 protected void consoleSetTerrainHeights(string module, string[] args)
154 { 154 {
155 string num = args[3]; 155 string num = args[3];
@@ -198,31 +198,31 @@ namespace OpenSim.Region.CoreModules.World.Estate
198 m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; 198 m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
199 break; 199 break;
200 } 200 }
201 201
202 m_module.Scene.RegionInfo.RegionSettings.Save(); 202 m_module.Scene.RegionInfo.RegionSettings.Save();
203 m_module.TriggerRegionInfoChange(); 203 m_module.TriggerRegionInfoChange();
204 m_module.sendRegionHandshakeToAll(); 204 m_module.sendRegionHandshakeToAll();
205 } 205 }
206 } 206 }
207 } 207 }
208 208
209 protected void ShowEstatesCommand(string module, string[] cmd) 209 protected void ShowEstatesCommand(string module, string[] cmd)
210 { 210 {
211 StringBuilder report = new StringBuilder(); 211 StringBuilder report = new StringBuilder();
212 RegionInfo ri = m_module.Scene.RegionInfo; 212 RegionInfo ri = m_module.Scene.RegionInfo;
213 EstateSettings es = ri.EstateSettings; 213 EstateSettings es = ri.EstateSettings;
214 214
215 report.AppendFormat("Estate information for region {0}\n", ri.RegionName); 215 report.AppendFormat("Estate information for region {0}\n", ri.RegionName);
216 report.AppendFormat( 216 report.AppendFormat(
217 "{0,-20} {1,-7} {2,-20}\n", 217 "{0,-20} {1,-7} {2,-20}\n",
218 "Estate Name", 218 "Estate Name",
219 "ID", 219 "ID",
220 "Owner"); 220 "Owner");
221 221
222 report.AppendFormat( 222 report.AppendFormat(
223 "{0,-20} {1,-7} {2,-20}\n", 223 "{0,-20} {1,-7} {2,-20}\n",
224 es.EstateName, es.EstateID, m_module.UserManager.GetUserName(es.EstateOwner)); 224 es.EstateName, es.EstateID, m_module.UserManager.GetUserName(es.EstateOwner));
225 225
226 MainConsole.Instance.Output(report.ToString()); 226 MainConsole.Instance.Output(report.ToString());
227 } 227 }
228 #endregion 228 #endregion
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 80fa08a..924f448 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -33,15 +33,19 @@ using System.Linq;
33using System.Reflection; 33using System.Reflection;
34using System.Security; 34using System.Security;
35using System.Timers; 35using System.Timers;
36using System.Threading;
36using log4net; 37using log4net;
37using Mono.Addins; 38using Mono.Addins;
38using Nini.Config; 39using Nini.Config;
39using OpenMetaverse; 40using OpenMetaverse;
40using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
44using RegionFlags = OpenMetaverse.RegionFlags; 46using RegionFlags = OpenMetaverse.RegionFlags;
47using Timer = System.Timers.Timer;
48
45 49
46namespace OpenSim.Region.CoreModules.World.Estate 50namespace OpenSim.Region.CoreModules.World.Estate
47{ 51{
@@ -53,8 +57,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
53 private Timer m_regionChangeTimer = new Timer(); 57 private Timer m_regionChangeTimer = new Timer();
54 public Scene Scene { get; private set; } 58 public Scene Scene { get; private set; }
55 public IUserManagement UserManager { get; private set; } 59 public IUserManagement UserManager { get; private set; }
56 60
57 protected EstateManagementCommands m_commands; 61 protected EstateManagementCommands m_commands;
58 62
59 /// <summary> 63 /// <summary>
60 /// If false, region restart requests from the client are blocked even if they are otherwise legitimate. 64 /// If false, region restart requests from the client are blocked even if they are otherwise legitimate.
@@ -67,14 +71,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
67 public event ChangeDelegate OnRegionInfoChange; 71 public event ChangeDelegate OnRegionInfoChange;
68 public event ChangeDelegate OnEstateInfoChange; 72 public event ChangeDelegate OnEstateInfoChange;
69 public event MessageDelegate OnEstateMessage; 73 public event MessageDelegate OnEstateMessage;
74 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
75 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
76
77 private int m_delayCount = 0;
70 78
71 #region Region Module interface 79 #region Region Module interface
72 80
73 public string Name { get { return "EstateManagementModule"; } } 81 public string Name { get { return "EstateManagementModule"; } }
74
75 public Type ReplaceableInterface { get { return null; } }
76 82
77 public void Initialise(IConfigSource source) 83 public Type ReplaceableInterface { get { return null; } }
84
85 public void Initialise(IConfigSource source)
78 { 86 {
79 AllowRegionRestartFromClient = true; 87 AllowRegionRestartFromClient = true;
80 88
@@ -83,7 +91,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
83 if (config != null) 91 if (config != null)
84 AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true); 92 AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true);
85 } 93 }
86 94
87 public void AddRegion(Scene scene) 95 public void AddRegion(Scene scene)
88 { 96 {
89 Scene = scene; 97 Scene = scene;
@@ -95,20 +103,24 @@ namespace OpenSim.Region.CoreModules.World.Estate
95 103
96 m_commands = new EstateManagementCommands(this); 104 m_commands = new EstateManagementCommands(this);
97 m_commands.Initialise(); 105 m_commands.Initialise();
106
107 m_regionChangeTimer.Interval = 10000;
108 m_regionChangeTimer.Elapsed += RaiseRegionInfoChange;
109 m_regionChangeTimer.AutoReset = false;
98 } 110 }
99 111
100 public void RemoveRegion(Scene scene) {} 112 public void RemoveRegion(Scene scene) {}
101 113
102 public void RegionLoaded(Scene scene) 114 public void RegionLoaded(Scene scene)
103 { 115 {
104 // Sets up the sun module based no the saved Estate and Region Settings 116 // Sets up the sun module based no the saved Estate and Region Settings
105 // DO NOT REMOVE or the sun will stop working 117 // DO NOT REMOVE or the sun will stop working
106 scene.TriggerEstateSunUpdate(); 118 scene.TriggerEstateSunUpdate();
107 119
108 UserManager = scene.RequestModuleInterface<IUserManagement>(); 120 UserManager = scene.RequestModuleInterface<IUserManagement>();
109 } 121 }
110 122
111 public void Close() 123 public void Close()
112 { 124 {
113 m_commands.Close(); 125 m_commands.Close();
114 } 126 }
@@ -142,6 +154,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
142 flags |= RegionFlags.AllowParcelChanges; 154 flags |= RegionFlags.AllowParcelChanges;
143 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) 155 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch)
144 flags |= RegionFlags.BlockParcelSearch; 156 flags |= RegionFlags.BlockParcelSearch;
157 if (Scene.RegionInfo.RegionSettings.GodBlockSearch)
158 flags |= (RegionFlags)(1 << 11);
159 if (Scene.RegionInfo.RegionSettings.Casino)
160 flags |= (RegionFlags)(1 << 10);
145 161
146 if (Scene.RegionInfo.RegionSettings.FixedSun) 162 if (Scene.RegionInfo.RegionSettings.FixedSun)
147 flags |= RegionFlags.SunFixed; 163 flags |= RegionFlags.SunFixed;
@@ -194,6 +210,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
194 change(Scene.RegionInfo.RegionID); 210 change(Scene.RegionInfo.RegionID);
195 } 211 }
196 212
213 protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e)
214 {
215 ChangeDelegate change = OnRegionInfoChange;
216
217 if (change != null)
218 change(Scene.RegionInfo.RegionID);
219 }
220
197 public void TriggerRegionInfoChange() 221 public void TriggerRegionInfoChange()
198 { 222 {
199 m_regionChangeTimer.Stop(); 223 m_regionChangeTimer.Stop();
@@ -423,7 +447,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
423 Scene.RegionInfo.EstateSettings.EstateID); 447 Scene.RegionInfo.EstateSettings.EstateID);
424 448
425 remote_client.SendEstateList(invoice, 449 remote_client.SendEstateList(invoice,
426 (int)Constants.EstateAccessCodex.AccessOptions, 450 (int)Constants.EstateAccessCodex.AllowedAccess,
427 Scene.RegionInfo.EstateSettings.EstateAccess, 451 Scene.RegionInfo.EstateSettings.EstateAccess,
428 Scene.RegionInfo.EstateSettings.EstateID); 452 Scene.RegionInfo.EstateSettings.EstateID);
429 453
@@ -462,7 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
462 486
463 if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity) 487 if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity)
464 Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; 488 Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents;
465 else 489 else
466 Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity; 490 Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity;
467 491
468 Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; 492 Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor;
@@ -554,6 +578,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
554 bool UseEstateSun, bool UseFixedSun, float SunHour, 578 bool UseEstateSun, bool UseFixedSun, float SunHour,
555 bool UseGlobal, bool EstateFixedSun, float EstateSunHour) 579 bool UseGlobal, bool EstateFixedSun, float EstateSunHour)
556 { 580 {
581 double lastwaterlevel = Scene.RegionInfo.RegionSettings.WaterHeight;
557 // Water Height 582 // Water Height
558 Scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight; 583 Scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight;
559 584
@@ -566,6 +591,9 @@ namespace OpenSim.Region.CoreModules.World.Estate
566 Scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun; 591 Scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun;
567 Scene.RegionInfo.RegionSettings.SunPosition = SunHour; 592 Scene.RegionInfo.RegionSettings.SunPosition = SunHour;
568 593
594 if(Scene.PhysicsEnabled && Scene.PhysicsScene != null && lastwaterlevel != WaterHeight)
595 Scene.PhysicsScene.SetWaterLevel(WaterHeight);
596
569 Scene.TriggerEstateSunUpdate(); 597 Scene.TriggerEstateSunUpdate();
570 598
571 //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString()); 599 //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString());
@@ -587,6 +615,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
587 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 615 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
588 if (restartModule != null) 616 if (restartModule != null)
589 { 617 {
618 if (timeInSeconds == -1)
619 {
620 m_delayCount++;
621 if (m_delayCount > 3)
622 return;
623
624 restartModule.DelayRestart(3600, "Restart delayed by region manager");
625 return;
626 }
627
590 List<int> times = new List<int>(); 628 List<int> times = new List<int>();
591 while (timeInSeconds > 0) 629 while (timeInSeconds > 0)
592 { 630 {
@@ -602,7 +640,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
602 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false); 640 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false);
603 641
604 m_log.InfoFormat( 642 m_log.InfoFormat(
605 "User {0} requested restart of region {1} in {2} seconds", 643 "User {0} requested restart of region {1} in {2} seconds",
606 remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0); 644 remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0);
607 } 645 }
608 } 646 }
@@ -610,236 +648,363 @@ namespace OpenSim.Region.CoreModules.World.Estate
610 private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID) 648 private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID)
611 { 649 {
612// m_log.DebugFormat( 650// m_log.DebugFormat(
613// "[ESTATE MANAGEMENT MODULE]: Handling request from {0} to change estate covenant to {1}", 651// "[ESTATE MANAGEMENT MODULE]: Handling request from {0} to change estate covenant to {1}",
614// remoteClient.Name, estateCovenantID); 652// remoteClient.Name, estateCovenantID);
615 653
616 Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; 654 Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID;
617 Scene.RegionInfo.RegionSettings.CovenantChangedDateTime = Util.UnixTimeSinceEpoch(); 655 Scene.RegionInfo.RegionSettings.CovenantChangedDateTime = Util.UnixTimeSinceEpoch();
618 Scene.RegionInfo.RegionSettings.Save(); 656 Scene.RegionInfo.RegionSettings.Save();
619 TriggerRegionInfoChange(); 657 TriggerRegionInfoChange();
620 } 658 }
621 659
622 private void handleEstateAccessDeltaRequest(IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user) 660 private object deltareqLock = new object();
661 private bool runnigDeltaExec = false;
662
663 private class EstateAccessDeltaRequest
664 {
665 public IClientAPI remote_client;
666 public UUID invoice;
667 public int estateAccessType;
668 public UUID user;
669 }
670
671 private OpenSim.Framework.BlockingQueue<EstateAccessDeltaRequest> deltaRequests = new OpenSim.Framework.BlockingQueue<EstateAccessDeltaRequest>();
672
673 private void handleEstateAccessDeltaRequest(IClientAPI _remote_client, UUID _invoice, int _estateAccessType, UUID _user)
623 { 674 {
624 // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc. 675 // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc.
625 676
626 if (user == Scene.RegionInfo.EstateSettings.EstateOwner) 677 if (_user == Scene.RegionInfo.EstateSettings.EstateOwner)
627 return; // never process EO 678 return; // never process EO
628 679
629 if ((estateAccessType & 4) != 0) // User add 680 EstateAccessDeltaRequest newreq = new EstateAccessDeltaRequest();
681 newreq.remote_client = _remote_client;
682 newreq.invoice = _invoice;
683 newreq.estateAccessType = _estateAccessType;
684 newreq.user = _user;
685
686 deltaRequests.Enqueue(newreq);
687
688 lock(deltareqLock)
630 { 689 {
631 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) 690 if(!runnigDeltaExec)
632 { 691 {
633 if ((estateAccessType & 1) != 0) // All estates 692 runnigDeltaExec = true;
693 WorkManager.RunInThreadPool(execDeltaRequests,null,"execDeltaRequests");
694 }
695 }
696 }
697
698 private void execDeltaRequests(object o)
699 {
700 IClientAPI remote_client;
701 UUID invoice;
702 int estateAccessType;
703 UUID user;
704 Dictionary<int,EstateSettings> changed = new Dictionary<int,EstateSettings>();
705 Dictionary<IClientAPI,UUID> sendAllowedOrBanList = new Dictionary<IClientAPI,UUID>();
706 Dictionary<IClientAPI,UUID> sendManagers = new Dictionary<IClientAPI,UUID>();
707 Dictionary<IClientAPI,UUID> sendGroups = new Dictionary<IClientAPI,UUID>();
708
709 List<EstateSettings> otherEstates = new List<EstateSettings>();
710
711 bool sentAllowedFull = false;
712 bool sentBansFull = false;
713 bool sentGroupsFull = false;
714 bool sentManagersFull = false;
715
716 while(Scene.IsRunning)
717 {
718 EstateAccessDeltaRequest req = deltaRequests.Dequeue(500);
719
720 if(!Scene.IsRunning)
721 break;
722
723 if(req == null)
724 {
725 if(changed.Count > 0)
634 { 726 {
635 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 727 foreach(EstateSettings est in changed.Values)
636 EstateSettings estateSettings; 728 Scene.EstateDataService.StoreEstateSettings(est);
637 729
638 foreach (int estateID in estateIDs) 730 TriggerEstateInfoChange();
639 {
640 if (estateID != Scene.RegionInfo.EstateSettings.EstateID)
641 {
642 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID);
643 estateSettings.AddEstateUser(user);
644 Scene.EstateDataService.StoreEstateSettings(estateSettings);
645 }
646 }
647 } 731 }
648 732
649 Scene.RegionInfo.EstateSettings.AddEstateUser(user); 733 EstateSettings es = Scene.RegionInfo.EstateSettings;
650 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 734 foreach(KeyValuePair<IClientAPI,UUID> kvp in sendAllowedOrBanList)
735 {
736 IClientAPI cli = kvp.Key;
737 UUID invoive = kvp.Value;
738 cli.SendEstateList(invoive, (int)Constants.EstateAccessCodex.AllowedAccess, es.EstateAccess, es.EstateID);
739 cli.SendBannedUserList(invoive, es.EstateBans, es.EstateID);
740 }
741 sendAllowedOrBanList.Clear();
651 742
652 TriggerEstateInfoChange(); 743 foreach(KeyValuePair<IClientAPI,UUID> kvp in sendManagers)
653 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, Scene.RegionInfo.EstateSettings.EstateAccess, Scene.RegionInfo.EstateSettings.EstateID); 744 {
745 IClientAPI cli = kvp.Key;
746 cli.SendEstateList(kvp.Value, (int)Constants.EstateAccessCodex.EstateManagers, es.EstateManagers, es.EstateID);
747 }
748 foreach(KeyValuePair<IClientAPI,UUID> kvp in sendGroups)
749 {
750 IClientAPI cli = kvp.Key;
751 cli.SendEstateList(kvp.Value, (int)Constants.EstateAccessCodex.AllowedGroups, es.EstateGroups, es.EstateID);
752 }
753 otherEstates.Clear();
754 sendAllowedOrBanList.Clear();
755 sendManagers.Clear();
756 sendGroups.Clear();
757 changed.Clear();
758 lock(deltareqLock)
759 {
760 if(deltaRequests.Count() != 0)
761 continue;
762 runnigDeltaExec = false;
763 return;
764 }
654 } 765 }
655 else 766
767 remote_client = req.remote_client;
768 if(!remote_client.IsActive)
769 continue;
770
771 invoice = req.invoice;
772 user = req.user;
773
774 estateAccessType = req.estateAccessType;
775
776 bool needReply = ((estateAccessType & 1024) == 0);
777 bool doOtherEstates = ((estateAccessType & 3) != 0);
778
779 EstateSettings thisSettings = Scene.RegionInfo.EstateSettings;
780 int thisEstateID =(int)thisSettings.EstateID;
781
782 UUID agentID = remote_client.AgentId;
783
784 bool isadmin = Scene.Permissions.IsAdministrator(agentID);
785 // just i case recheck rights
786 if (!isadmin && !Scene.Permissions.IsEstateManager(agentID))
656 { 787 {
657 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 788 remote_client.SendAlertMessage("Method EstateAccess Failed, you don't have permissions");
789 continue;
658 } 790 }
659 791
660 } 792 otherEstates.Clear();
661 793 if(doOtherEstates)
662 if ((estateAccessType & 8) != 0) // User remove
663 {
664 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
665 { 794 {
666 if ((estateAccessType & 1) != 0) // All estates 795 UUID thisOwner = Scene.RegionInfo.EstateSettings.EstateOwner;
796 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(thisOwner);
797 foreach (int estateID in estateIDs)
667 { 798 {
668 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 799 if (estateID == thisEstateID)
800 continue;
801
669 EstateSettings estateSettings; 802 EstateSettings estateSettings;
803 if(changed.ContainsKey(estateID))
804 estateSettings = changed[estateID];
805 else
806 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID);
807
808 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
809 continue;
810 otherEstates.Add(estateSettings);
811 }
812 estateIDs.Clear();
813 }
670 814
671 foreach (int estateID in estateIDs) 815 // the commands
816 // first the ones allowed for estate managers on this region
817 if ((estateAccessType & 4) != 0) // User add
818 {
819 if(thisSettings.EstateUsersCount() >= (int)Constants.EstateAccessLimits.AllowedAccess)
820 {
821 if(!sentAllowedFull)
672 { 822 {
673 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 823 sentAllowedFull = true;
824 remote_client.SendAlertMessage("Estate Allowed users list is full");
825 }
826 }
827 else
828 {
829 if (doOtherEstates)
830 {
831 foreach (EstateSettings estateSettings in otherEstates)
674 { 832 {
675 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 833 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
676 estateSettings.RemoveEstateUser(user); 834 continue;
677 Scene.EstateDataService.StoreEstateSettings(estateSettings); 835 if(estateSettings.EstateUsersCount() >= (int)Constants.EstateAccessLimits.AllowedAccess)
836 continue;
837 estateSettings.AddEstateUser(user);
838 estateSettings.RemoveBan(user);
839 changed[(int)estateSettings.EstateID] = estateSettings;
678 } 840 }
679 } 841 }
680 }
681 842
682 Scene.RegionInfo.EstateSettings.RemoveEstateUser(user); 843 thisSettings.AddEstateUser(user);
683 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 844 thisSettings.RemoveBan(user);
845 changed[thisEstateID] = thisSettings;;
684 846
685 TriggerEstateInfoChange(); 847 if(needReply)
686 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, Scene.RegionInfo.EstateSettings.EstateAccess, Scene.RegionInfo.EstateSettings.EstateID); 848 sendAllowedOrBanList[remote_client] = invoice;
849 }
687 } 850 }
688 else 851
852 if ((estateAccessType & 8) != 0) // User remove
689 { 853 {
690 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 854 if (doOtherEstates) // All estates
855 {
856 foreach (EstateSettings estateSettings in otherEstates)
857 {
858 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
859 continue;
860 estateSettings.RemoveEstateUser(user);
861 changed[(int)estateSettings.EstateID] = estateSettings;
862 }
863 }
864
865 thisSettings.RemoveEstateUser(user);
866 changed[thisEstateID] = thisSettings;;
867
868 if(needReply)
869 sendAllowedOrBanList[remote_client] = invoice;
691 } 870 }
692 }
693 871
694 if ((estateAccessType & 16) != 0) // Group add 872 if ((estateAccessType & 16) != 0) // Group add
695 {
696 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
697 { 873 {
698 if ((estateAccessType & 1) != 0) // All estates 874 if(thisSettings.EstateGroupsCount() >= (int)Constants.EstateAccessLimits.AllowedGroups)
699 { 875 {
700 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 876 if(!sentGroupsFull)
701 EstateSettings estateSettings; 877 {
702 878 sentGroupsFull = true;
703 foreach (int estateID in estateIDs) 879 remote_client.SendAlertMessage("Estate Allowed groups list is full");
880 }
881 }
882 else
883 {
884 if (doOtherEstates) // All estates
704 { 885 {
705 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 886 foreach (EstateSettings estateSettings in otherEstates)
706 { 887 {
707 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 888 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
889 continue;
890 if(estateSettings.EstateGroupsCount() >= (int)Constants.EstateAccessLimits.AllowedGroups)
891 continue;
708 estateSettings.AddEstateGroup(user); 892 estateSettings.AddEstateGroup(user);
709 Scene.EstateDataService.StoreEstateSettings(estateSettings); 893 changed[(int)estateSettings.EstateID] = estateSettings;
710 } 894 }
711 } 895 }
712 }
713 896
714 Scene.RegionInfo.EstateSettings.AddEstateGroup(user); 897 thisSettings.AddEstateGroup(user);
715 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 898 changed[thisEstateID] = thisSettings;
716 899
717 TriggerEstateInfoChange(); 900 sendGroups[remote_client] = invoice;
718 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, Scene.RegionInfo.EstateSettings.EstateGroups, Scene.RegionInfo.EstateSettings.EstateID); 901 }
719 }
720 else
721 {
722 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
723 } 902 }
724 }
725 903
726 if ((estateAccessType & 32) != 0) // Group remove 904 if ((estateAccessType & 32) != 0) // Group remove
727 {
728 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
729 { 905 {
730 if ((estateAccessType & 1) != 0) // All estates 906 if (doOtherEstates) // All estates
731 { 907 {
732 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 908 foreach (EstateSettings estateSettings in otherEstates)
733 EstateSettings estateSettings;
734
735 foreach (int estateID in estateIDs)
736 { 909 {
737 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 910 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
738 { 911 continue;
739 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 912 estateSettings.RemoveEstateGroup(user);
740 estateSettings.RemoveEstateGroup(user); 913 changed[(int)estateSettings.EstateID] = estateSettings;
741 Scene.EstateDataService.StoreEstateSettings(estateSettings);
742 }
743 } 914 }
744 } 915 }
745 916
746 Scene.RegionInfo.EstateSettings.RemoveEstateGroup(user); 917 thisSettings.RemoveEstateGroup(user);
747 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 918 changed[thisEstateID] = thisSettings;
748 919
749 TriggerEstateInfoChange(); 920 sendGroups[remote_client] = invoice;
750 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, Scene.RegionInfo.EstateSettings.EstateGroups, Scene.RegionInfo.EstateSettings.EstateID);
751 } 921 }
752 else
753 {
754 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
755 }
756 }
757 922
758 if ((estateAccessType & 64) != 0) // Ban add 923 if ((estateAccessType & 64) != 0) // Ban add
759 {
760 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
761 { 924 {
762 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
763 925
764 bool alreadyInList = false; 926 if(thisSettings.EstateBansCount() >= (int)Constants.EstateAccessLimits.EstateBans)
765
766 for (int i = 0; i < banlistcheck.Length; i++)
767 { 927 {
768 if (user == banlistcheck[i].BannedUserID) 928 if(!sentBansFull)
769 { 929 {
770 alreadyInList = true; 930 sentBansFull = true;
771 break; 931 remote_client.SendAlertMessage("Estate Ban list is full");
772 } 932 }
773
774 } 933 }
775 if (!alreadyInList) 934 else
776 { 935 {
936 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
777 937
778 if ((estateAccessType & 1) != 0) // All estates 938 bool alreadyInList = false;
779 {
780 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner);
781 EstateSettings estateSettings;
782 939
783 foreach (int estateID in estateIDs) 940 for (int i = 0; i < banlistcheck.Length; i++)
941 {
942 if (user == banlistcheck[i].BannedUserID)
943 {
944 alreadyInList = true;
945 break;
946 }
947 }
948 if (!alreadyInList)
949 {
950 if (doOtherEstates) // All estates
784 { 951 {
785 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 952 foreach (EstateSettings estateSettings in otherEstates)
786 { 953 {
954 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
955 continue;
956
957 if(estateSettings.EstateBansCount() >= (int)Constants.EstateAccessLimits.EstateBans)
958 continue;
959
787 EstateBan bitem = new EstateBan(); 960 EstateBan bitem = new EstateBan();
788 961
789 bitem.BannedUserID = user; 962 bitem.BannedUserID = user;
790 bitem.EstateID = (uint)estateID; 963 bitem.EstateID = estateSettings.EstateID;
791 bitem.BannedHostAddress = "0.0.0.0"; 964 bitem.BannedHostAddress = "0.0.0.0";
792 bitem.BannedHostIPMask = "0.0.0.0"; 965 bitem.BannedHostIPMask = "0.0.0.0";
793 966
794 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID);
795 estateSettings.AddBan(bitem); 967 estateSettings.AddBan(bitem);
796 Scene.EstateDataService.StoreEstateSettings(estateSettings); 968 estateSettings.RemoveEstateUser(user);
969 changed[(int)estateSettings.EstateID] = estateSettings;
797 } 970 }
798 } 971 }
799 }
800 972
801 EstateBan item = new EstateBan(); 973 EstateBan item = new EstateBan();
802 974
803 item.BannedUserID = user; 975 item.BannedUserID = user;
804 item.EstateID = Scene.RegionInfo.EstateSettings.EstateID; 976 item.EstateID = Scene.RegionInfo.EstateSettings.EstateID;
805 item.BannedHostAddress = "0.0.0.0"; 977 item.BannedHostAddress = "0.0.0.0";
806 item.BannedHostIPMask = "0.0.0.0"; 978 item.BannedHostIPMask = "0.0.0.0";
807 979
808 Scene.RegionInfo.EstateSettings.AddBan(item); 980 thisSettings.AddBan(item);
809 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 981 thisSettings.RemoveEstateUser(user);
982 changed[thisEstateID] = thisSettings;
810 983
811 TriggerEstateInfoChange(); 984 ScenePresence s = Scene.GetScenePresence(user);
812 985 if (s != null)
813 ScenePresence s = Scene.GetScenePresence(user);
814 if (s != null)
815 {
816 if (!s.IsChildAgent)
817 { 986 {
818 if (!Scene.TeleportClientHome(user, s.ControllingClient)) 987 if (!s.IsChildAgent)
819 { 988 {
820 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); 989 if (!Scene.TeleportClientHome(user, s.ControllingClient))
821 Scene.CloseAgent(s.UUID, false); 990 {
991 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
992 Scene.CloseAgent(s.UUID, false);
993 }
822 } 994 }
823 } 995 }
824 } 996 }
825 997 else
826 } 998 {
827 else 999 remote_client.SendAlertMessage("User is already on the region ban list");
828 { 1000 }
829 remote_client.SendAlertMessage("User is already on the region ban list"); 1001 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
1002 if(needReply)
1003 sendAllowedOrBanList[remote_client] = invoice;
830 } 1004 }
831 //Scene.RegionInfo.regionBanlist.Add(Manager(user);
832 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID);
833 }
834 else
835 {
836 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
837 } 1005 }
838 }
839 1006
840 if ((estateAccessType & 128) != 0) // Ban remove 1007 if ((estateAccessType & 128) != 0) // Ban remove
841 {
842 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
843 { 1008 {
844 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 1009 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
845 1010
@@ -855,107 +1020,93 @@ namespace OpenSim.Region.CoreModules.World.Estate
855 break; 1020 break;
856 } 1021 }
857 } 1022 }
858 1023
859 if (alreadyInList && listitem != null) 1024 if (alreadyInList && listitem != null)
860 { 1025 {
861 if ((estateAccessType & 1) != 0) // All estates 1026 if (doOtherEstates) // All estates
862 { 1027 {
863 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 1028 foreach (EstateSettings estateSettings in otherEstates)
864 EstateSettings estateSettings;
865
866 foreach (int estateID in estateIDs)
867 { 1029 {
868 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 1030 if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
869 { 1031 continue;
870 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 1032 estateSettings.RemoveBan(user);
871 estateSettings.RemoveBan(user); 1033 changed[(int)estateSettings.EstateID] = estateSettings;
872 Scene.EstateDataService.StoreEstateSettings(estateSettings);
873 }
874 } 1034 }
875 } 1035 }
876 1036
877 Scene.RegionInfo.EstateSettings.RemoveBan(listitem.BannedUserID); 1037 thisSettings.RemoveBan(listitem.BannedUserID);
878 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 1038 changed[thisEstateID] = thisSettings;
879
880 TriggerEstateInfoChange();
881 } 1039 }
882 else 1040 else
883 { 1041 {
884 remote_client.SendAlertMessage("User is not on the region ban list"); 1042 remote_client.SendAlertMessage("User is not on the region ban list");
885 } 1043 }
886 1044
887 //Scene.RegionInfo.regionBanlist.Add(Manager(user); 1045 if(needReply)
888 remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); 1046 sendAllowedOrBanList[remote_client] = invoice;
889 } 1047 }
890 else 1048
1049 // last the ones only for owners of this region
1050 if (!Scene.Permissions.CanIssueEstateCommand(agentID, true))
891 { 1051 {
892 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 1052 remote_client.SendAlertMessage("Method EstateAccess Failed, you don't have permissions");
1053 continue;
893 } 1054 }
894 }
895 1055
896 if ((estateAccessType & 256) != 0) // Manager add 1056 if ((estateAccessType & 256) != 0) // Manager add
897 {
898 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
899 { 1057 {
900 if ((estateAccessType & 1) != 0) // All estates 1058 if(thisSettings.EstateManagersCount() >= (int)Constants.EstateAccessLimits.EstateManagers)
901 { 1059 {
902 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 1060 if(!sentManagersFull)
903 EstateSettings estateSettings; 1061 {
904 1062 sentManagersFull = true;
905 foreach (int estateID in estateIDs) 1063 remote_client.SendAlertMessage("Estate Managers list is full");
1064 }
1065 }
1066 else
1067 {
1068 if (doOtherEstates) // All estates
906 { 1069 {
907 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 1070 foreach (EstateSettings estateSettings in otherEstates)
908 { 1071 {
909 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 1072 if(!isadmin && !estateSettings.IsEstateOwner(agentID)) // redundante check?
1073 continue;
1074 if(estateSettings.EstateManagersCount() >= (int)Constants.EstateAccessLimits.EstateManagers)
1075 continue;
910 estateSettings.AddEstateManager(user); 1076 estateSettings.AddEstateManager(user);
911 Scene.EstateDataService.StoreEstateSettings(estateSettings); 1077 changed[(int)estateSettings.EstateID] = estateSettings;
912 } 1078 }
913 } 1079 }
914 }
915 1080
916 Scene.RegionInfo.EstateSettings.AddEstateManager(user); 1081 thisSettings.AddEstateManager(user);
917 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 1082 changed[thisEstateID] = thisSettings;
918 1083
919 TriggerEstateInfoChange(); 1084 sendManagers[remote_client] = invoice;
920 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, Scene.RegionInfo.EstateSettings.EstateID); 1085 }
921 }
922 else
923 {
924 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
925 } 1086 }
926 }
927 1087
928 if ((estateAccessType & 512) != 0) // Manager remove 1088 if ((estateAccessType & 512) != 0) // Manager remove
929 {
930 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
931 { 1089 {
932 if ((estateAccessType & 1) != 0) // All estates 1090 if (doOtherEstates) // All estates
933 { 1091 {
934 List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); 1092 foreach (EstateSettings estateSettings in otherEstates)
935 EstateSettings estateSettings;
936
937 foreach (int estateID in estateIDs)
938 { 1093 {
939 if (estateID != Scene.RegionInfo.EstateSettings.EstateID) 1094 if(!isadmin && !estateSettings.IsEstateOwner(agentID))
940 { 1095 continue;
941 estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); 1096
942 estateSettings.RemoveEstateManager(user); 1097 estateSettings.RemoveEstateManager(user);
943 Scene.EstateDataService.StoreEstateSettings(estateSettings); 1098 changed[(int)estateSettings.EstateID] = estateSettings;
944 }
945 } 1099 }
946 } 1100 }
947 1101
948 Scene.RegionInfo.EstateSettings.RemoveEstateManager(user); 1102 thisSettings.RemoveEstateManager(user);
949 Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); 1103 changed[thisEstateID] = thisSettings;
950 1104
951 TriggerEstateInfoChange(); 1105 sendManagers[remote_client] = invoice;
952 remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, Scene.RegionInfo.EstateSettings.EstateID);
953 }
954 else
955 {
956 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
957 } 1106 }
958 } 1107 }
1108 lock(deltareqLock)
1109 runnigDeltaExec = false;
959 } 1110 }
960 1111
961 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 1112 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
@@ -1007,7 +1158,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1007 IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) 1158 IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message)
1008 { 1159 {
1009 IDialogModule dm = Scene.RequestModuleInterface<IDialogModule>(); 1160 IDialogModule dm = Scene.RequestModuleInterface<IDialogModule>();
1010 1161
1011 if (dm != null) 1162 if (dm != null)
1012 dm.SendNotificationToUsersInRegion(senderID, senderName, message); 1163 dm.SendNotificationToUsersInRegion(senderID, senderName, message);
1013 } 1164 }
@@ -1044,13 +1195,20 @@ namespace OpenSim.Region.CoreModules.World.Estate
1044 1195
1045 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) 1196 private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey)
1046 { 1197 {
1198 EstateTeleportOneUserHomeRequest evOverride = OnEstateTeleportOneUserHomeRequest;
1199 if(evOverride != null)
1200 {
1201 evOverride(remover_client, invoice, senderID, prey);
1202 return;
1203 }
1204
1047 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) 1205 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false))
1048 return; 1206 return;
1049 1207
1050 if (prey != UUID.Zero) 1208 if (prey != UUID.Zero)
1051 { 1209 {
1052 ScenePresence s = Scene.GetScenePresence(prey); 1210 ScenePresence s = Scene.GetScenePresence(prey);
1053 if (s != null) 1211 if (s != null && !s.IsDeleted && !s.IsInTransit)
1054 { 1212 {
1055 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 1213 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
1056 { 1214 {
@@ -1063,6 +1221,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
1063 1221
1064 private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID) 1222 private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID)
1065 { 1223 {
1224 EstateTeleportAllUsersHomeRequest evOverride = OnEstateTeleportAllUsersHomeRequest;
1225 if(evOverride != null)
1226 {
1227 evOverride(remover_client, invoice, senderID);
1228 return;
1229 }
1230
1066 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) 1231 if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false))
1067 return; 1232 return;
1068 1233
@@ -1084,7 +1249,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1084 } 1249 }
1085 }); 1250 });
1086 } 1251 }
1087 1252
1088 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) 1253 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
1089 { 1254 {
1090 lock (this) 1255 lock (this)
@@ -1167,7 +1332,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1167 if (TerrainUploader == null) 1332 if (TerrainUploader == null)
1168 { 1333 {
1169 m_log.DebugFormat( 1334 m_log.DebugFormat(
1170 "[TERRAIN]: Started receiving terrain upload for region {0} from {1}", 1335 "[TERRAIN]: Started receiving terrain upload for region {0} from {1}",
1171 Scene.Name, remote_client.Name); 1336 Scene.Name, remote_client.Name);
1172 1337
1173 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName); 1338 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
@@ -1187,25 +1352,43 @@ namespace OpenSim.Region.CoreModules.World.Estate
1187 { 1352 {
1188 // Save terrain here 1353 // Save terrain here
1189 ITerrainModule terr = Scene.RequestModuleInterface<ITerrainModule>(); 1354 ITerrainModule terr = Scene.RequestModuleInterface<ITerrainModule>();
1190 1355
1191 if (terr != null) 1356 if (terr != null)
1192 { 1357 {
1358 string file = Util.cacheDir() + "/terrain_";
1359 try
1360 {
1361 file = file + Uri.EscapeDataString(Scene.Name) + ".raw";
1362 }
1363 catch (Exception)
1364 {
1365 file = file + ".raw";
1366 }
1193// m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + Scene.RegionInfo.RegionName); 1367// m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + Scene.RegionInfo.RegionName);
1194 if (File.Exists(Util.dataDir() + "/terrain.raw")) 1368 if (File.Exists(file))
1369 {
1370 File.Delete(file);
1371 }
1372 terr.SaveToFile(file);
1373
1374 byte[] bdata;
1375 using(FileStream input = new FileStream(file, FileMode.Open))
1376 {
1377 bdata = new byte[input.Length];
1378 input.Read(bdata, 0, (int)input.Length);
1379 }
1380 if(bdata == null || bdata.Length == 0)
1195 { 1381 {
1196 File.Delete(Util.dataDir() + "/terrain.raw"); 1382 remote_client.SendAlertMessage("Terrain error");
1383 return;
1197 } 1384 }
1198 terr.SaveToFile(Util.dataDir() + "/terrain.raw");
1199 1385
1200 FileStream input = new FileStream(Util.dataDir() + "/terrain.raw", FileMode.Open);
1201 byte[] bdata = new byte[input.Length];
1202 input.Read(bdata, 0, (int)input.Length);
1203 remote_client.SendAlertMessage("Terrain file written, starting download..."); 1386 remote_client.SendAlertMessage("Terrain file written, starting download...");
1204 Scene.XferManager.AddNewFile("terrain.raw", bdata); 1387 string xfername = (UUID.Random()).ToString();
1388 Scene.XferManager.AddNewFile(xfername, bdata);
1205 1389
1206 m_log.DebugFormat("[CLIENT]: Sending terrain for region {0} to {1}", Scene.Name, remote_client.Name); 1390 m_log.DebugFormat("[CLIENT]: Sending terrain for region {0} to {1}", Scene.Name, remote_client.Name);
1207 1391 remote_client.SendInitiateDownload(xfername, clientFileName);
1208 remote_client.SendInitiateDownload("terrain.raw", clientFileName);
1209 } 1392 }
1210 } 1393 }
1211 1394
@@ -1319,7 +1502,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
1319 1502
1320 public void sendRegionInfoPacketToAll() 1503 public void sendRegionInfoPacketToAll()
1321 { 1504 {
1322 Scene.ForEachRootClient(delegate(IClientAPI client) 1505// Scene.ForEachRootClient(delegate(IClientAPI client)
1506 Scene.ForEachClient(delegate(IClientAPI client)
1323 { 1507 {
1324 HandleRegionInfoRequest(client); 1508 HandleRegionInfoRequest(client);
1325 }); 1509 });
@@ -1443,7 +1627,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1443 Scene.RegionInfo.EstateSettings.FixedSun, 1627 Scene.RegionInfo.EstateSettings.FixedSun,
1444 (float)Scene.RegionInfo.EstateSettings.SunPosition); 1628 (float)Scene.RegionInfo.EstateSettings.SunPosition);
1445 1629
1446 sendRegionInfoPacketToAll(); 1630// sendRegionInfoPacketToAll(); already done by setRegionTerrainSettings
1447 } 1631 }
1448 1632
1449 1633
@@ -1477,7 +1661,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
1477 sendRegionHandshake(client); 1661 sendRegionHandshake(client);
1478 } 1662 }
1479 1663
1480 private uint GetEstateFlags() 1664
1665 public uint GetEstateFlags()
1481 { 1666 {
1482 RegionFlags flags = RegionFlags.None; 1667 RegionFlags flags = RegionFlags.None;
1483 1668
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
index 4bb3799..f3c8aa8 100644
--- a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateModule.cs
@@ -45,12 +45,14 @@ using Mono.Addins;
45namespace OpenSim.Region.CoreModules.World.Estate 45namespace OpenSim.Region.CoreModules.World.Estate
46{ 46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")]
48 public class XEstateModule : ISharedRegionModule 48 public class EstateModule : ISharedRegionModule
49 { 49 {
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 protected List<Scene> m_Scenes = new List<Scene>(); 52 protected List<Scene> m_Scenes = new List<Scene>();
53 protected bool m_InInfoUpdate = false; 53 protected bool m_InInfoUpdate = false;
54 private string token = "7db8eh2gvgg45jj";
55 protected bool m_enabled = false;
54 56
55 public bool InInfoUpdate 57 public bool InInfoUpdate
56 { 58 {
@@ -67,19 +69,33 @@ namespace OpenSim.Region.CoreModules.World.Estate
67 69
68 public void Initialise(IConfigSource config) 70 public void Initialise(IConfigSource config)
69 { 71 {
70 int port = 0; 72 uint port = MainServer.Instance.Port;
71 73
72 IConfig estateConfig = config.Configs["Estate"]; 74 IConfig estateConfig = config.Configs["Estates"];
73 if (estateConfig != null) 75 if (estateConfig != null)
74 { 76 {
75 port = estateConfig.GetInt("Port", 0); 77 if (estateConfig.GetString("EstateCommunicationsHandler", Name) == Name)
78 m_enabled = true;
79 else
80 return;
81
82 port = (uint)estateConfig.GetInt("Port", 0);
83 // this will need to came from somewhere else
84 token = estateConfig.GetString("Token", token);
85 }
86 else
87 {
88 m_enabled = true;
76 } 89 }
77 90
78 m_EstateConnector = new EstateConnector(this); 91 m_EstateConnector = new EstateConnector(this, token, port);
92
93 if(port == 0)
94 port = MainServer.Instance.Port;
79 95
80 // Instantiate the request handler 96 // Instantiate the request handler
81 IHttpServer server = MainServer.GetHttpServer((uint)port); 97 IHttpServer server = MainServer.GetHttpServer(port);
82 server.AddStreamHandler(new EstateRequestHandler(this)); 98 server.AddStreamHandler(new EstateRequestHandler(this, token));
83 } 99 }
84 100
85 public void PostInitialise() 101 public void PostInitialise()
@@ -92,24 +108,31 @@ namespace OpenSim.Region.CoreModules.World.Estate
92 108
93 public void AddRegion(Scene scene) 109 public void AddRegion(Scene scene)
94 { 110 {
111 if (!m_enabled)
112 return;
113
95 lock (m_Scenes) 114 lock (m_Scenes)
96 m_Scenes.Add(scene); 115 m_Scenes.Add(scene);
97
98 scene.EventManager.OnNewClient += OnNewClient;
99 } 116 }
100 117
101 public void RegionLoaded(Scene scene) 118 public void RegionLoaded(Scene scene)
102 { 119 {
120 if (!m_enabled)
121 return;
122
103 IEstateModule em = scene.RequestModuleInterface<IEstateModule>(); 123 IEstateModule em = scene.RequestModuleInterface<IEstateModule>();
104 124
105 em.OnRegionInfoChange += OnRegionInfoChange; 125 em.OnRegionInfoChange += OnRegionInfoChange;
106 em.OnEstateInfoChange += OnEstateInfoChange; 126 em.OnEstateInfoChange += OnEstateInfoChange;
107 em.OnEstateMessage += OnEstateMessage; 127 em.OnEstateMessage += OnEstateMessage;
128 em.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest;
129 em.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest;
108 } 130 }
109 131
110 public void RemoveRegion(Scene scene) 132 public void RemoveRegion(Scene scene)
111 { 133 {
112 scene.EventManager.OnNewClient -= OnNewClient; 134 if (!m_enabled)
135 return;
113 136
114 lock (m_Scenes) 137 lock (m_Scenes)
115 m_Scenes.Remove(scene); 138 m_Scenes.Remove(scene);
@@ -181,13 +204,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
181 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message); 204 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message);
182 } 205 }
183 206
184 private void OnNewClient(IClientAPI client)
185 {
186 client.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest;
187 client.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest;
188
189 }
190
191 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey) 207 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey)
192 { 208 {
193 if (prey == UUID.Zero) 209 if (prey == UUID.Zero)
@@ -205,16 +221,18 @@ namespace OpenSim.Region.CoreModules.World.Estate
205 221
206 foreach (Scene s in Scenes) 222 foreach (Scene s in Scenes)
207 { 223 {
208 if (s == scene)
209 continue; // Already handles by estate module
210 if (s.RegionInfo.EstateSettings.EstateID != estateID) 224 if (s.RegionInfo.EstateSettings.EstateID != estateID)
211 continue; 225 continue;
212 226
213 ScenePresence p = scene.GetScenePresence(prey); 227 ScenePresence p = scene.GetScenePresence(prey);
214 if (p != null && !p.IsChildAgent) 228 if (p != null && !p.IsChildAgent )
215 { 229 {
216 p.ControllingClient.SendTeleportStart(16); 230 if(!p.IsDeleted && !p.IsInTransit)
217 scene.TeleportClientHome(prey, p.ControllingClient); 231 {
232 p.ControllingClient.SendTeleportStart(16);
233 scene.TeleportClientHome(prey, p.ControllingClient);
234 }
235 return;
218 } 236 }
219 } 237 }
220 238
@@ -235,8 +253,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
235 253
236 foreach (Scene s in Scenes) 254 foreach (Scene s in Scenes)
237 { 255 {
238 if (s == scene)
239 continue; // Already handles by estate module
240 if (s.RegionInfo.EstateSettings.EstateID != estateID) 256 if (s.RegionInfo.EstateSettings.EstateID != estateID)
241 continue; 257 continue;
242 258
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs
index ec5af2b..5eda8ab 100644
--- a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs
@@ -46,24 +46,27 @@ namespace OpenSim.Region.CoreModules.World.Estate
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 protected XEstateModule m_EstateModule; 49 protected EstateModule m_EstateModule;
50 protected Object m_RequestLock = new Object(); 50 protected Object m_RequestLock = new Object();
51 private string token;
51 52
52 public EstateRequestHandler(XEstateModule fmodule) 53 public EstateRequestHandler(EstateModule fmodule, string _token)
53 : base("POST", "/estate") 54 : base("POST", "/estate")
54 { 55 {
55 m_EstateModule = fmodule; 56 m_EstateModule = fmodule;
57 token = _token;
56 } 58 }
57 59
58 protected override byte[] ProcessRequest(string path, Stream requestData, 60 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 61 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 { 62 {
61 StreamReader sr = new StreamReader(requestData); 63 string body;
62 string body = sr.ReadToEnd(); 64 using(StreamReader sr = new StreamReader(requestData))
63 sr.Close(); 65 body = sr.ReadToEnd();
66
64 body = body.Trim(); 67 body = body.Trim();
65 68
66 m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body); 69 // m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body);
67 70
68 try 71 try
69 { 72 {
@@ -75,6 +78,15 @@ namespace OpenSim.Region.CoreModules.World.Estate
75 if (!request.ContainsKey("METHOD")) 78 if (!request.ContainsKey("METHOD"))
76 return FailureResult(); 79 return FailureResult();
77 80
81 if (!request.ContainsKey("TOKEN"))
82 return FailureResult();
83
84 string reqToken = request["TOKEN"].ToString();
85 request.Remove("TOKEN");
86
87 if(token != reqToken)
88 return FailureResult();
89
78 string method = request["METHOD"].ToString(); 90 string method = request["METHOD"].ToString();
79 request.Remove("METHOD"); 91 request.Remove("METHOD");
80 92
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
index 70c6028..22480e6 100644
--- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
@@ -53,7 +53,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
53namespace OpenSim.Region.CoreModules.World.Land 53namespace OpenSim.Region.CoreModules.World.Land
54{ 54{
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultDwellModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultDwellModule")]
56 public class DefaultDwellModule : IDwellModule, INonSharedRegionModule 56 public class DefaultDwellModule : INonSharedRegionModule, IDwellModule
57 { 57 {
58 private Scene m_scene; 58 private Scene m_scene;
59 private IConfigSource m_Config; 59 private IConfigSource m_Config;
@@ -88,16 +88,21 @@ namespace OpenSim.Region.CoreModules.World.Land
88 return; 88 return;
89 89
90 m_scene = scene; 90 m_scene = scene;
91 91 m_scene.RegisterModuleInterface<IDwellModule>(this);
92 m_scene.EventManager.OnNewClient += OnNewClient;
93 } 92 }
94 93
95 public void RegionLoaded(Scene scene) 94 public void RegionLoaded(Scene scene)
96 { 95 {
96 if (!m_Enabled)
97 return;
98 m_scene.EventManager.OnNewClient += OnNewClient;
97 } 99 }
98 100
99 public void RemoveRegion(Scene scene) 101 public void RemoveRegion(Scene scene)
100 { 102 {
103 if (!m_Enabled)
104 return;
105 m_scene.EventManager.OnNewClient -= OnNewClient;
101 } 106 }
102 107
103 public void Close() 108 public void Close()
@@ -115,12 +120,26 @@ namespace OpenSim.Region.CoreModules.World.Land
115 if (parcel == null) 120 if (parcel == null)
116 return; 121 return;
117 122
118 client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); 123 LandData land = parcel.LandData;
124 if(land!= null)
125 client.SendParcelDwellReply(localID, land.GlobalID, land.Dwell);
119 } 126 }
120 127
128
121 public int GetDwell(UUID parcelID) 129 public int GetDwell(UUID parcelID)
122 { 130 {
131 ILandObject parcel = m_scene.LandChannel.GetLandObject(parcelID);
132 if (parcel != null && parcel.LandData != null)
133 return (int)(parcel.LandData.Dwell);
134 return 0;
135 }
136
137 public int GetDwell(LandData land)
138 {
139 if (land != null)
140 return (int)(land.Dwell);
123 return 0; 141 return 0;
124 } 142 }
143
125 } 144 }
126} 145}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 73c592d..5ff063b 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -37,26 +37,37 @@ namespace OpenSim.Region.CoreModules.World.Land
37 { 37 {
38 #region Constants 38 #region Constants
39 39
40 public const float BAN_LINE_SAFETY_HEIGHT = 100;
40 //Land types set with flags in ParcelOverlay. 41 //Land types set with flags in ParcelOverlay.
41 //Only one of these can be used. 42 //Only one of these can be used.
42 public const float BAN_LINE_SAFETY_HIEGHT = 100; 43
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 44
46 //RequestResults (I think these are right, they seem to work): 45 //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 46 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 47 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
49 48
50 //ParcelSelectObjects 49 //ParcelSelectObjects
50 public const int LAND_SELECT_OBJECTS_OWNER = 2;
51 public const int LAND_SELECT_OBJECTS_GROUP = 4; 51 public const int LAND_SELECT_OBJECTS_GROUP = 4;
52 public const int LAND_SELECT_OBJECTS_OTHER = 8; 52 public const int LAND_SELECT_OBJECTS_OTHER = 8;
53 public const int LAND_SELECT_OBJECTS_OWNER = 2; 53
54 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101 54
55 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100 55 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
56 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010 56 // types 1 to 7 are exclusive
57 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001 57 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
58 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011 59 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
59 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000 60 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
61 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
62 public const byte LAND_TYPE_unused6 = 6;
63 public const byte LAND_TYPE_unused7 = 7;
64 // next are flags
65 public const byte LAND_FLAG_unused8 = 0x08; // this may become excluside in future
66 public const byte LAND_FLAG_HIDEAVATARS = 0x10;
67 public const byte LAND_FLAG_LOCALSOUND = 0x20;
68 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 0x40; //Equals 01000000
69 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 0x80; //Equals 10000000
70
60 71
61 //These are other constants. Yay! 72 //These are other constants. Yay!
62 public const int START_LAND_LOCAL_ID = 1; 73 public const int START_LAND_LOCAL_ID = 1;
@@ -64,7 +75,7 @@ namespace OpenSim.Region.CoreModules.World.Land
64 #endregion 75 #endregion
65 76
66 private readonly Scene m_scene; 77 private readonly Scene m_scene;
67 private readonly LandManagementModule m_landManagementModule; 78 private readonly LandManagementModule m_landManagementModule;
68 79
69 public LandChannel(Scene scene, LandManagementModule landManagementMod) 80 public LandChannel(Scene scene, LandManagementModule landManagementMod)
70 { 81 {
@@ -80,7 +91,7 @@ namespace OpenSim.Region.CoreModules.World.Land
80 { 91 {
81 return m_landManagementModule.GetLandObject(x_float, y_float); 92 return m_landManagementModule.GetLandObject(x_float, y_float);
82 } 93 }
83 94
84 ILandObject obj = new LandObject(UUID.Zero, false, m_scene); 95 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
85 obj.LandData.Name = "NO LAND"; 96 obj.LandData.Name = "NO LAND";
86 return obj; 97 return obj;
@@ -95,6 +106,15 @@ namespace OpenSim.Region.CoreModules.World.Land
95 return null; 106 return null;
96 } 107 }
97 108
109 public ILandObject GetLandObject(UUID GlobalID)
110 {
111 if (m_landManagementModule != null)
112 {
113 return m_landManagementModule.GetLandObject(GlobalID);
114 }
115 return null;
116 }
117
98 public ILandObject GetLandObject(Vector3 position) 118 public ILandObject GetLandObject(Vector3 position)
99 { 119 {
100 return GetLandObject(position.X, position.Y); 120 return GetLandObject(position.X, position.Y);
@@ -106,7 +126,7 @@ namespace OpenSim.Region.CoreModules.World.Land
106 { 126 {
107 return m_landManagementModule.GetLandObject(x, y); 127 return m_landManagementModule.GetLandObject(x, y);
108 } 128 }
109 129
110 ILandObject obj = new LandObject(UUID.Zero, false, m_scene); 130 ILandObject obj = new LandObject(UUID.Zero, false, m_scene);
111 obj.LandData.Name = "NO LAND"; 131 obj.LandData.Name = "NO LAND";
112 return obj; 132 return obj;
@@ -121,7 +141,7 @@ namespace OpenSim.Region.CoreModules.World.Land
121 141
122 return new List<ILandObject>(); 142 return new List<ILandObject>();
123 } 143 }
124 144
125 public void Clear(bool setupDefaultParcel) 145 public void Clear(bool setupDefaultParcel)
126 { 146 {
127 if (m_landManagementModule != null) 147 if (m_landManagementModule != null)
@@ -156,6 +176,14 @@ namespace OpenSim.Region.CoreModules.World.Land
156 } 176 }
157 } 177 }
158 178
179 public void SendParcelsOverlay(IClientAPI client)
180 {
181 if (m_landManagementModule != null)
182 {
183 m_landManagementModule.SendParcelOverlay(client);
184 }
185 }
186
159 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) 187 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
160 { 188 {
161 if (m_landManagementModule != null) 189 if (m_landManagementModule != null)
@@ -171,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.Land
171 m_landManagementModule.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id); 199 m_landManagementModule.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
172 } 200 }
173 } 201 }
174 202
175 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 203 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
176 { 204 {
177 if (m_landManagementModule != null) 205 if (m_landManagementModule != null)
@@ -203,7 +231,13 @@ namespace OpenSim.Region.CoreModules.World.Land
203 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); 231 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
204 } 232 }
205 } 233 }
206 234 public void sendClientInitialLandInfo(IClientAPI remoteClient)
235 {
236 if (m_landManagementModule != null)
237 {
238 m_landManagementModule.sendClientInitialLandInfo(remoteClient);
239 }
240 }
207 #endregion 241 #endregion
208 } 242 }
209} 243}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 92f6c1b..b1f5122 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -41,6 +41,7 @@ using OpenSim.Framework;
41using OpenSim.Framework.Capabilities; 41using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers; 43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Monitoring;
44using OpenSim.Framework.Servers.HttpServer; 45using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 47using OpenSim.Region.Framework.Scenes;
@@ -52,7 +53,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52namespace OpenSim.Region.CoreModules.World.Land 53namespace OpenSim.Region.CoreModules.World.Land
53{ 54{
54 // used for caching 55 // used for caching
55 internal class ExtendedLandData 56 internal class ExtendedLandData
56 { 57 {
57 public LandData LandData; 58 public LandData LandData;
58 public ulong RegionHandle; 59 public ulong RegionHandle;
@@ -69,9 +70,8 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// <summary> 70 /// <summary>
70 /// Minimum land unit size in region co-ordinates. 71 /// Minimum land unit size in region co-ordinates.
71 /// </summary> 72 /// </summary>
72 public const int LandUnit = 4;
73 73
74 private static readonly string remoteParcelRequestPath = "0009/"; 74 public const int LandUnit = 4;
75 75
76 private LandChannel landChannel; 76 private LandChannel landChannel;
77 private Scene m_scene; 77 private Scene m_scene;
@@ -89,20 +89,27 @@ namespace OpenSim.Region.CoreModules.World.Land
89 /// <value> 89 /// <value>
90 /// Land objects keyed by local id 90 /// Land objects keyed by local id
91 /// </value> 91 /// </value>
92 private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>(); 92// private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
93
94 //ubit: removed the readonly so i can move it around
95 private Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
96 private Dictionary<UUID, int> m_landUUIDList = new Dictionary<UUID, int>();
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 bool m_showBansLines = true;
102 private UUID DefaultGodParcelGroup;
103 private string DefaultGodParcelName;
97 104
98 // caches ExtendedLandData 105 // caches ExtendedLandData
99 private Cache parcelInfoCache; 106 private Cache parcelInfoCache;
100 107
101
102 /// <summary> 108 /// <summary>
103 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. 109 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
104 /// </summary> 110 /// </summary>
105 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>(); 111 private HashSet<UUID> forcedPosition = new HashSet<UUID>();
112
106 113
107 // Enables limiting parcel layer info transmission when doing simple updates 114 // Enables limiting parcel layer info transmission when doing simple updates
108 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } 115 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; }
@@ -125,6 +132,11 @@ namespace OpenSim.Region.CoreModules.World.Land
125 { 132 {
126 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); 133 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance);
127 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); 134 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance);
135 DefaultGodParcelGroup = new UUID(landManagementConfig.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
136 DefaultGodParcelName = landManagementConfig.GetString("DefaultAdministratorParcelName", "Default Parcel");
137 bool disablebans = landManagementConfig.GetBoolean("DisableParcelBans", !m_allowedForcefulBans);
138 m_allowedForcefulBans = !disablebans;
139 m_showBansLines = landManagementConfig.GetBoolean("ShowParcelBansLines", m_showBansLines);
128 } 140 }
129 } 141 }
130 142
@@ -132,17 +144,20 @@ namespace OpenSim.Region.CoreModules.World.Land
132 { 144 {
133 m_scene = scene; 145 m_scene = scene;
134 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; 146 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit];
147
135 landChannel = new LandChannel(scene, this); 148 landChannel = new LandChannel(scene, this);
136 149
137 parcelInfoCache = new Cache(); 150 parcelInfoCache = new Cache();
138 parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache 151 parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache
139 parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0); 152 parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0);
140 153
154 m_scene.EventManager.OnObjectAddedToScene += EventManagerOnParcelPrimCountAdd;
141 m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd; 155 m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd;
156
157 m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
142 m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate; 158 m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate;
143 m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
144 m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate; 159 m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate;
145 160
146 m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel; 161 m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel;
147 m_scene.EventManager.OnClientMovement += EventManagerOnClientMovement; 162 m_scene.EventManager.OnClientMovement += EventManagerOnClientMovement;
148 m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy; 163 m_scene.EventManager.OnValidateLandBuy += EventManagerOnValidateLandBuy;
@@ -152,14 +167,14 @@ namespace OpenSim.Region.CoreModules.World.Land
152 m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement; 167 m_scene.EventManager.OnSignificantClientMovement += EventManagerOnSignificantClientMovement;
153 m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage; 168 m_scene.EventManager.OnNoticeNoLandDataFromStorage += EventManagerOnNoLandDataFromStorage;
154 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 169 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
155 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; 170 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
156 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; 171 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
157 172
158 lock (m_scene) 173 lock (m_scene)
159 { 174 {
160 m_scene.LandChannel = (ILandChannel)landChannel; 175 m_scene.LandChannel = (ILandChannel)landChannel;
161 } 176 }
162 177
163 RegisterCommands(); 178 RegisterCommands();
164 } 179 }
165 180
@@ -172,8 +187,8 @@ namespace OpenSim.Region.CoreModules.World.Land
172 } 187 }
173 188
174 public void RemoveRegion(Scene scene) 189 public void RemoveRegion(Scene scene)
175 { 190 {
176 // TODO: Release event manager listeners here 191 // TODO: Release event manager listeners here
177 } 192 }
178 193
179// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason) 194// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
@@ -181,7 +196,7 @@ namespace OpenSim.Region.CoreModules.World.Land
181// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y); 196// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
182// reason = "You are not allowed to enter this sim."; 197// reason = "You are not allowed to enter this sim.";
183// return nearestParcel != null; 198// return nearestParcel != null;
184// } 199// }
185 200
186 void EventManagerOnNewClient(IClientAPI client) 201 void EventManagerOnNewClient(IClientAPI client)
187 { 202 {
@@ -199,18 +214,10 @@ namespace OpenSim.Region.CoreModules.World.Land
199 client.OnParcelReclaim += ClientOnParcelReclaim; 214 client.OnParcelReclaim += ClientOnParcelReclaim;
200 client.OnParcelInfoRequest += ClientOnParcelInfoRequest; 215 client.OnParcelInfoRequest += ClientOnParcelInfoRequest;
201 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; 216 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
202 client.OnPreAgentUpdate += ClientOnPreAgentUpdate;
203 client.OnParcelEjectUser += ClientOnParcelEjectUser; 217 client.OnParcelEjectUser += ClientOnParcelEjectUser;
204 client.OnParcelFreezeUser += ClientOnParcelFreezeUser; 218 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
205 client.OnSetStartLocationRequest += ClientOnSetHome; 219 client.OnSetStartLocationRequest += ClientOnSetHome;
206 220 client.OnParcelBuyPass += ClientParcelBuyPass;
207
208 EntityBase presenceEntity;
209 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
210 {
211 SendLandUpdate((ScenePresence)presenceEntity, true);
212 SendParcelOverlay(client);
213 }
214 } 221 }
215 222
216 public void EventMakeChildAgent(ScenePresence avatar) 223 public void EventMakeChildAgent(ScenePresence avatar)
@@ -218,52 +225,6 @@ namespace OpenSim.Region.CoreModules.World.Land
218 avatar.currentParcelUUID = UUID.Zero; 225 avatar.currentParcelUUID = UUID.Zero;
219 } 226 }
220 227
221 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
222 {
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 }
266
267 public void Close() 228 public void Close()
268 { 229 {
269 } 230 }
@@ -291,7 +252,10 @@ namespace OpenSim.Region.CoreModules.World.Land
291 lock (m_landList) 252 lock (m_landList)
292 { 253 {
293 if (m_landList.TryGetValue(local_id, out land)) 254 if (m_landList.TryGetValue(local_id, out land))
255 {
294 land.LandData = newData; 256 land.LandData = newData;
257 m_landUUIDList[newData.GlobalID] = local_id;
258 }
295 } 259 }
296 260
297 if (land != null) 261 if (land != null)
@@ -312,28 +276,35 @@ namespace OpenSim.Region.CoreModules.World.Land
312 //Remove all the land objects in the sim and add a blank, full sim land object set to public 276 //Remove all the land objects in the sim and add a blank, full sim land object set to public
313 lock (m_landList) 277 lock (m_landList)
314 { 278 {
279 foreach(ILandObject parcel in m_landList.Values)
280 parcel.Clear();
281
315 m_landList.Clear(); 282 m_landList.Clear();
283 m_landUUIDList.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 }
320 289
321 /// <summary> 290 /// <summary>
322 /// Create a default parcel that spans the entire region and is owned by the estate owner. 291 /// Create a default parcel that spans the entire region and is owned by the estate owner.
323 /// </summary> 292 /// </summary>
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 LandData ldata = fullSimParcel.LandData;
334 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 303 ldata.SimwideArea = ldata.Area;
335 304 ldata.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
336 return AddLandObject(fullSimParcel); 305 ldata.ClaimDate = Util.UnixTimeSinceEpoch();
306
307 return AddLandObject(fullSimParcel);
337 } 308 }
338 309
339 public List<ILandObject> AllParcels() 310 public List<ILandObject> AllParcels()
@@ -347,9 +318,9 @@ namespace OpenSim.Region.CoreModules.World.Land
347 public List<ILandObject> ParcelsNearPoint(Vector3 position) 318 public List<ILandObject> ParcelsNearPoint(Vector3 position)
348 { 319 {
349 List<ILandObject> parcelsNear = new List<ILandObject>(); 320 List<ILandObject> parcelsNear = new List<ILandObject>();
350 for (int x = -4; x <= 4; x += 4) 321 for (int x = -8; x <= 8; x += 4)
351 { 322 {
352 for (int y = -4; y <= 4; y += 4) 323 for (int y = -8; y <= 8; y += 4)
353 { 324 {
354 ILandObject check = GetLandObject(position.X + x, position.Y + y); 325 ILandObject check = GetLandObject(position.X + x, position.Y + y);
355 if (check != null) 326 if (check != null)
@@ -365,33 +336,99 @@ namespace OpenSim.Region.CoreModules.World.Land
365 return parcelsNear; 336 return parcelsNear;
366 } 337 }
367 338
368 public void SendYouAreBannedNotice(ScenePresence avatar) 339 // checks and enforces bans or restrictions
340 // returns true if enforced
341 public bool EnforceBans(ILandObject land, ScenePresence avatar)
369 { 342 {
370 if (AllowedForcefulBans) 343 Vector3 agentpos = avatar.AbsolutePosition;
344 float h = m_scene.GetGroundHeight(agentpos.X, agentpos.Y) + LandChannel.BAN_LINE_SAFETY_HEIGHT;
345 float zdif = avatar.AbsolutePosition.Z - h;
346 if (zdif > 0 )
347 {
348 forcedPosition.Remove(avatar.UUID);
349 avatar.lastKnownAllowedPosition = agentpos;
350 return false;
351 }
352
353 bool ban = false;
354 string reason = "";
355 if (land.IsRestrictedFromLand(avatar.UUID))
371 { 356 {
372 avatar.ControllingClient.SendAlertMessage( 357 reason = "You do not have access to the parcel";
373 "You are not allowed on this parcel because you are banned. Please go away."); 358 ban = true;
359 }
360
361 if (land.IsBannedFromLand(avatar.UUID))
362 {
363 if ( m_allowedForcefulBans)
364 {
365 reason ="You are banned from parcel";
366 ban = true;
367 }
368 else if(!ban)
369 {
370 if (forcedPosition.Contains(avatar.UUID))
371 avatar.ControllingClient.SendAlertMessage("You are banned from parcel, please leave by your own will");
372 forcedPosition.Remove(avatar.UUID);
373 avatar.lastKnownAllowedPosition = agentpos;
374 return false;
375 }
376 }
377
378 if(ban)
379 {
380 if (!forcedPosition.Contains(avatar.UUID))
381 avatar.ControllingClient.SendAlertMessage(reason);
382
383 if(zdif > -4f)
384 {
385
386 agentpos.Z = h + 4.0f;
387 ForceAvatarToPosition(avatar, agentpos);
388 return true;
389 }
390
391 if (land.ContainsPoint((int)avatar.lastKnownAllowedPosition.X,
392 (int) avatar.lastKnownAllowedPosition.Y))
393 {
394 Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
395 if (pos == null)
396 {
397 forcedPosition.Remove(avatar.UUID);
398 m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
399 }
400 else
401 ForceAvatarToPosition(avatar, (Vector3)pos);
402 }
403 else
404 {
405 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
406 }
407 return true;
374 } 408 }
375 else 409 else
376 { 410 {
377 avatar.ControllingClient.SendAlertMessage( 411 forcedPosition.Remove(avatar.UUID);
378 "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim!"); 412 avatar.lastKnownAllowedPosition = agentpos;
413 return false;
379 } 414 }
380 } 415 }
381 416
382 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) 417 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
383 { 418 {
384 if (m_scene.Permissions.IsGod(avatar.UUID)) return; 419 if (m_scene.Permissions.IsGod(avatar.UUID)) return;
385 if (position.HasValue)
386 {
387 forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position;
388 }
389 }
390 420
391 public void SendYouAreRestrictedNotice(ScenePresence avatar) 421 if (!position.HasValue)
392 { 422 return;
393 avatar.ControllingClient.SendAlertMessage( 423
394 "You are not allowed on this parcel because the land owner has restricted access."); 424 if(avatar.MovingToTarget)
425 avatar.ResetMoveToTarget();
426 avatar.AbsolutePosition = position.Value;
427 avatar.lastKnownAllowedPosition = position.Value;
428 avatar.Velocity = Vector3.Zero;
429 if(avatar.IsSatOnObject)
430 avatar.StandUp();
431 forcedPosition.Add(avatar.UUID);
395 } 432 }
396 433
397 public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID) 434 public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID)
@@ -404,29 +441,12 @@ namespace OpenSim.Region.CoreModules.World.Land
404 parcelAvatarIsEntering = m_landList[localLandID]; 441 parcelAvatarIsEntering = m_landList[localLandID];
405 } 442 }
406 443
407 if (parcelAvatarIsEntering != null) 444 if (parcelAvatarIsEntering != null &&
445 avatar.currentParcelUUID != parcelAvatarIsEntering.LandData.GlobalID)
408 { 446 {
409 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) 447 SendLandUpdate(avatar, parcelAvatarIsEntering);
410 { 448 avatar.currentParcelUUID = parcelAvatarIsEntering.LandData.GlobalID;
411 if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) 449 EnforceBans(parcelAvatarIsEntering, avatar);
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 } 450 }
431 } 451 }
432 } 452 }
@@ -434,7 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Land
434 public void SendOutNearestBanLine(IClientAPI client) 454 public void SendOutNearestBanLine(IClientAPI client)
435 { 455 {
436 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 456 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
437 if (sp == null || sp.IsChildAgent) 457 if (sp == null || sp.IsDeleted)
438 return; 458 return;
439 459
440 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition); 460 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition);
@@ -454,98 +474,180 @@ namespace OpenSim.Region.CoreModules.World.Land
454 return; 474 return;
455 } 475 }
456 476
457 public void SendLandUpdate(ScenePresence avatar, bool force) 477 public void sendClientInitialLandInfo(IClientAPI remoteClient)
458 { 478 {
459 ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 479 ScenePresence avatar;
460 (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
461 480
462 if (over != null) 481 if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out avatar))
482 return;
483
484 if (!avatar.IsChildAgent)
463 { 485 {
464 if (force) 486 ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
465 { 487 if (over == null)
466 if (!avatar.IsChildAgent) 488 return;
467 {
468 over.SendLandUpdateToClient(avatar.ControllingClient);
469 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
470 m_scene.RegionInfo.RegionID);
471 }
472 }
473 489
474 if (avatar.currentParcelUUID != over.LandData.GlobalID) 490 avatar.currentParcelUUID = over.LandData.GlobalID;
475 { 491 over.SendLandUpdateToClient(avatar.ControllingClient);
476 if (!avatar.IsChildAgent)
477 {
478 over.SendLandUpdateToClient(avatar.ControllingClient);
479 avatar.currentParcelUUID = over.LandData.GlobalID;
480 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
481 m_scene.RegionInfo.RegionID);
482 }
483 }
484 } 492 }
493 SendParcelOverlay(remoteClient);
485 } 494 }
486 495
487 public void SendLandUpdate(ScenePresence avatar) 496 public void SendLandUpdate(ScenePresence avatar, ILandObject over)
488 { 497 {
489 SendLandUpdate(avatar, false); 498 if (avatar.IsChildAgent)
490 } 499 return;
491 500
492 public void EventManagerOnSignificantClientMovement(ScenePresence clientAvatar) 501 if (over != null)
493 {
494 SendLandUpdate(clientAvatar);
495 SendOutNearestBanLine(clientAvatar.ControllingClient);
496 ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y);
497 if (parcel != null)
498 { 502 {
499 if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && 503 over.SendLandUpdateToClient(avatar.ControllingClient);
500 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) 504// sl doesnt seem to send this now, as it used 2
501 { 505// SendParcelOverlay(avatar.ControllingClient);
502 EventManagerOnAvatarEnteringNewParcel(clientAvatar, parcel.LandData.LocalID,
503 m_scene.RegionInfo.RegionID);
504 //They are going under the safety line!
505 if (!parcel.IsBannedFromLand(clientAvatar.UUID))
506 {
507 clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false;
508 }
509 }
510 else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT &&
511 parcel.IsBannedFromLand(clientAvatar.UUID))
512 {
513 //once we've sent the message once, keep going toward the target until we are done
514 if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId))
515 {
516 SendYouAreBannedNotice(clientAvatar);
517 ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar));
518 }
519 }
520 else if (parcel.IsRestrictedFromLand(clientAvatar.UUID))
521 {
522 //once we've sent the message once, keep going toward the target until we are done
523 if (forcedPosition.ContainsKey(clientAvatar.ControllingClient.AgentId))
524 {
525 SendYouAreRestrictedNotice(clientAvatar);
526 ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar));
527 }
528 }
529 else
530 {
531 //when we are finally in a safe place, lets release the forced position lock
532 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId);
533 }
534 } 506 }
535 } 507 }
536 508
509 public void EventManagerOnSignificantClientMovement(ScenePresence avatar)
510 {
511 if (avatar.IsChildAgent)
512 return;
513
514 if ( m_allowedForcefulBans && m_showBansLines)
515 SendOutNearestBanLine(avatar.ControllingClient);
516 }
517
537 /// <summary> 518 /// <summary>
538 /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. 519 /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance.
539 /// </summary> 520 /// </summary>
540 /// <param name="avatar"></param> 521 /// <param name="avatar"></param>
541 public void EventManagerOnClientMovement(ScenePresence avatar) 522 public void EventManagerOnClientMovement(ScenePresence avatar)
542 { 523 {
524 if (avatar.IsChildAgent)
525 return;
526
543 Vector3 pos = avatar.AbsolutePosition; 527 Vector3 pos = avatar.AbsolutePosition;
544 ILandObject over = GetLandObject(pos.X, pos.Y); 528 ILandObject over = GetLandObject(pos.X, pos.Y);
545 if (over != null) 529 if (over != null)
546 { 530 {
547 if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || pos.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)) 531 EnforceBans(over, avatar);
548 avatar.lastKnownAllowedPosition = pos; 532 pos = avatar.AbsolutePosition;
533 ILandObject newover = GetLandObject(pos.X, pos.Y);
534 if(over != newover || avatar.currentParcelUUID != newover.LandData.GlobalID)
535 {
536 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar,
537 newover.LandData.LocalID, m_scene.RegionInfo.RegionID);
538 }
539 }
540 }
541
542 public void ClientParcelBuyPass(IClientAPI remote_client, UUID targetID, int landLocalID)
543 {
544 ILandObject land;
545 lock (m_landList)
546 {
547 m_landList.TryGetValue(landLocalID, out land);
548 }
549 // trivial checks
550 if(land == null)
551 return;
552
553 LandData ldata = land.LandData;
554
555 if(ldata == null)
556 return;
557
558 if(ldata.OwnerID == targetID)
559 return;
560
561 if(ldata.PassHours == 0)
562 return;
563
564 // don't allow passes on group owned until we can give money to groups
565 if(ldata.IsGroupOwned)
566 {
567 remote_client.SendAgentAlertMessage("pass to group owned parcel not suported", false);
568 return;
569 }
570
571 if((ldata.Flags & (uint)ParcelFlags.UsePassList) == 0)
572 return;
573
574 int cost = ldata.PassPrice;
575
576 int idx = land.LandData.ParcelAccessList.FindIndex(
577 delegate(LandAccessEntry e)
578 {
579 if (e.AgentID == targetID && e.Flags == AccessList.Access)
580 return true;
581 return false;
582 });
583 int now = Util.UnixTimeSinceEpoch();
584 int expires = (int)(3600.0 * ldata.PassHours + 0.5f);
585 int currenttime = -1;
586 if (idx != -1)
587 {
588 if(ldata.ParcelAccessList[idx].Expires == 0)
589 {
590 remote_client.SendAgentAlertMessage("You already have access to parcel", false);
591 return;
592 }
593
594 currenttime = ldata.ParcelAccessList[idx].Expires - now;
595 if(currenttime > (int)(0.25f * expires + 0.5f))
596 {
597 if(currenttime > 3600)
598 remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.###} hours",
599 currenttime/3600f), false);
600 else if(currenttime > 60)
601 remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.##} minutes",
602 currenttime/60f), false);
603 else
604 remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.#} seconds",
605 currenttime), false);
606 return;
607 }
608 }
609
610 LandAccessEntry entry = new LandAccessEntry();
611 entry.AgentID = targetID;
612 entry.Flags = AccessList.Access;
613 entry.Expires = now + expires;
614 if(currenttime > 0)
615 entry.Expires += currenttime;
616 IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
617 if(cost != 0 && mm != null)
618 {
619 WorkManager.RunInThreadPool(
620 delegate
621 {
622 string regionName = m_scene.RegionInfo.RegionName;
623
624 if (!mm.AmountCovered(remote_client.AgentId, cost))
625 {
626 remote_client.SendAgentAlertMessage(String.Format("Insufficient funds in region '{0}' money system", regionName), true);
627 return;
628 }
629
630 string payDescription = String.Format("Parcel '{0}' at region '{1} {2:0.###} hours access pass", ldata.Name, regionName, ldata.PassHours);
631
632 if(!mm.MoveMoney(remote_client.AgentId, ldata.OwnerID, cost,MoneyTransactionType.LandPassSale, payDescription))
633 {
634 remote_client.SendAgentAlertMessage("Sorry pass payment processing failed, please try again later", true);
635 return;
636 }
637
638 if (idx != -1)
639 ldata.ParcelAccessList.RemoveAt(idx);
640 ldata.ParcelAccessList.Add(entry);
641 m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
642 return;
643 }, null, "ParcelBuyPass");
644 }
645 else
646 {
647 if (idx != -1)
648 ldata.ParcelAccessList.RemoveAt(idx);
649 ldata.ParcelAccessList.Add(entry);
650 m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
549 } 651 }
550 } 652 }
551 653
@@ -589,7 +691,7 @@ namespace OpenSim.Region.CoreModules.World.Land
589 requiredPowers = GroupPowers.LandManageBanned; 691 requiredPowers = GroupPowers.LandManageBanned;
590 692
591 if (m_scene.Permissions.CanEditParcelProperties(agentID, 693 if (m_scene.Permissions.CanEditParcelProperties(agentID,
592 land, requiredPowers)) 694 land, requiredPowers, false))
593 { 695 {
594 land.UpdateAccessList(flags, transactionID, sequenceID, 696 land.UpdateAccessList(flags, transactionID, sequenceID,
595 sections, entries, remote_client); 697 sections, entries, remote_client);
@@ -605,13 +707,11 @@ namespace OpenSim.Region.CoreModules.World.Land
605 /// Adds a land object to the stored list and adds them to the landIDList to what they own 707 /// Adds a land object to the stored list and adds them to the landIDList to what they own
606 /// </summary> 708 /// </summary>
607 /// <param name="new_land"> 709 /// <param name="new_land">
608 /// The land object being added. 710 /// The land object being added.
609 /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted. 711 /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted.
610 /// </param> 712 /// </param>
611 public ILandObject AddLandObject(ILandObject land) 713 public ILandObject AddLandObject(ILandObject new_land)
612 { 714 {
613 ILandObject new_land = land.Copy();
614
615 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated 715 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated
616 // as a random UUID inside LandData initialization 716 // as a random UUID inside LandData initialization
617 if (m_primCountModule != null) 717 if (m_primCountModule != null)
@@ -623,18 +723,15 @@ namespace OpenSim.Region.CoreModules.World.Land
623 new_land.LandData.LocalID = newLandLocalID; 723 new_land.LandData.LocalID = newLandLocalID;
624 724
625 bool[,] landBitmap = new_land.GetLandBitmap(); 725 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)) 726 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
630 { 727 {
631 // Going to variable sized regions can cause mismatches 728 // 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})", 729 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) ); 730 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1));
634 } 731 }
635 else 732 else
636 { 733 {
637 // If other land objects still believe that they occupy any parts of the same space, 734 // If other land objects still believe that they occupy any parts of the same space,
638 // then do not allow the add to proceed. 735 // then do not allow the add to proceed.
639 for (int x = 0; x < landBitmap.GetLength(0); x++) 736 for (int x = 0; x < landBitmap.GetLength(0); x++)
640 { 737 {
@@ -652,7 +749,7 @@ namespace OpenSim.Region.CoreModules.World.Land
652 { 749 {
653 m_log.ErrorFormat( 750 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}", 751 "{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, 752 LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y,
656 lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name); 753 lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name);
657 754
658 return null; 755 return null;
@@ -668,10 +765,10 @@ namespace OpenSim.Region.CoreModules.World.Land
668 { 765 {
669 if (landBitmap[x, y]) 766 if (landBitmap[x, y])
670 { 767 {
671 // m_log.DebugFormat( 768 // m_log.DebugFormat(
672 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", 769 // "[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); 770 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
674 771
675 m_landIDList[x, y] = newLandLocalID; 772 m_landIDList[x, y] = newLandLocalID;
676 } 773 }
677 } 774 }
@@ -679,6 +776,7 @@ namespace OpenSim.Region.CoreModules.World.Land
679 } 776 }
680 777
681 m_landList.Add(newLandLocalID, new_land); 778 m_landList.Add(newLandLocalID, new_land);
779 m_landUUIDList[new_land.LandData.GlobalID] = newLandLocalID;
682 m_lastLandLocalID++; 780 m_lastLandLocalID++;
683 } 781 }
684 782
@@ -695,6 +793,7 @@ namespace OpenSim.Region.CoreModules.World.Land
695 public void removeLandObject(int local_id) 793 public void removeLandObject(int local_id)
696 { 794 {
697 ILandObject land; 795 ILandObject land;
796 UUID landGlobalID = UUID.Zero;
698 lock (m_landList) 797 lock (m_landList)
699 { 798 {
700 for (int x = 0; x < m_landIDList.GetLength(0); x++) 799 for (int x = 0; x < m_landIDList.GetLength(0); x++)
@@ -713,37 +812,47 @@ namespace OpenSim.Region.CoreModules.World.Land
713 812
714 land = m_landList[local_id]; 813 land = m_landList[local_id];
715 m_landList.Remove(local_id); 814 m_landList.Remove(local_id);
815 if(land != null && land.LandData != null)
816 {
817 landGlobalID = land.LandData.GlobalID;
818 m_landUUIDList.Remove(landGlobalID);
819 }
716 } 820 }
717 821
718 m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID); 822 if(landGlobalID != UUID.Zero)
823 {
824 m_scene.EventManager.TriggerLandObjectRemoved(landGlobalID);
825 land.Clear();
826 }
719 } 827 }
720 828
721 /// <summary> 829 /// <summary>
722 /// Clear the scene of all parcels 830 /// Clear the scene of all parcels
723 /// </summary> 831 /// </summary>
724 public void Clear(bool setupDefaultParcel) 832 public void Clear(bool setupDefaultParcel)
725 { 833 {
726 List<ILandObject> parcels; 834 Dictionary<int, ILandObject> landworkList;
835 // move to work pointer since we are deleting it all
727 lock (m_landList) 836 lock (m_landList)
728 { 837 {
729 parcels = new List<ILandObject>(m_landList.Values); 838 landworkList = m_landList;
839 m_landList = new Dictionary<int, ILandObject>();
730 } 840 }
731 841
732 foreach (ILandObject lo in parcels) 842 // this 2 methods have locks (now)
843 ResetSimLandObjects();
844
845 if (setupDefaultParcel)
846 CreateDefaultParcel();
847
848 // fire outside events unlocked
849 foreach (ILandObject lo in landworkList.Values)
733 { 850 {
734 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); 851 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID);
735 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); 852 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID);
736 } 853 }
854 landworkList.Clear();
737 855
738 lock (m_landList)
739 {
740 m_landList.Clear();
741
742 ResetSimLandObjects();
743 }
744
745 if (setupDefaultParcel)
746 CreateDefaultParcel();
747 } 856 }
748 857
749 private void performFinalLandJoin(ILandObject master, ILandObject slave) 858 private void performFinalLandJoin(ILandObject master, ILandObject slave)
@@ -762,11 +871,29 @@ namespace OpenSim.Region.CoreModules.World.Land
762 } 871 }
763 } 872 }
764 } 873 }
765 874 master.LandData.Dwell += slave.LandData.Dwell;
766 removeLandObject(slave.LandData.LocalID); 875 removeLandObject(slave.LandData.LocalID);
767 UpdateLandObject(master.LandData.LocalID, master.LandData); 876 UpdateLandObject(master.LandData.LocalID, master.LandData);
768 } 877 }
769 878
879 public ILandObject GetLandObject(UUID globalID)
880 {
881 lock (m_landList)
882 {
883 int lid = -1;
884 if(m_landUUIDList.TryGetValue(globalID, out lid) && lid >= 0)
885 {
886 if (m_landList.ContainsKey(lid))
887 {
888 return m_landList[lid];
889 }
890 else
891 m_landUUIDList.Remove(globalID); // auto heal
892 }
893 }
894 return null;
895 }
896
770 public ILandObject GetLandObject(int parcelLocalID) 897 public ILandObject GetLandObject(int parcelLocalID)
771 { 898 {
772 lock (m_landList) 899 lock (m_landList)
@@ -787,58 +914,37 @@ namespace OpenSim.Region.CoreModules.World.Land
787 /// <returns>Land object at the point supplied</returns> 914 /// <returns>Land object at the point supplied</returns>
788 public ILandObject GetLandObject(float x_float, float y_float) 915 public ILandObject GetLandObject(float x_float, float y_float)
789 { 916 {
790 return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */); 917 return GetLandObject((int)x_float, (int)y_float, true);
791 /* 918 }
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 919
798 try 920 // if x,y is off region this will return the parcel at cliped x,y
799 { 921 // as did code it replaces
800 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit)); 922 public ILandObject GetLandObjectClipedXY(float x, float y)
801 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit)); 923 {
802 } 924 //do clip inline
803 catch (OverflowException) 925 int avx = (int)x;
804 { 926 if (avx < 0)
805 return null; 927 avx = 0;
806 } 928 else if (avx >= m_scene.RegionInfo.RegionSizeX)
929 avx = (int)Constants.RegionSize - 1;
807 930
808 if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit) 931 int avy = (int)y;
809 || y >= (m_scene.RegionInfo.RegionSizeY / landUnit) 932 if (avy < 0)
810 || x < 0 933 avy = 0;
811 || y < 0) 934 else if (avy >= m_scene.RegionInfo.RegionSizeY)
812 { 935 avy = (int)Constants.RegionSize - 1;
813 return null;
814 }
815 936
816 lock (m_landList) 937 lock (m_landIDList)
817 { 938 {
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 939 try
829 { 940 {
830 if (m_landList.ContainsKey(m_landIDList[x, y])) 941 return m_landList[m_landIDList[avx / LandUnit, avy / LandUnit]];
831 return m_landList[m_landIDList[x, y]];
832 } 942 }
833 catch (Exception e) 943 catch (IndexOutOfRangeException)
834 { 944 {
835 m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})", 945 return null;
836 LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
837 } 946 }
838
839 return null;
840 } 947 }
841 */
842 } 948 }
843 949
844 // Public entry. 950 // Public entry.
@@ -848,33 +954,32 @@ namespace OpenSim.Region.CoreModules.World.Land
848 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */); 954 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
849 } 955 }
850 956
851 /// <summary> 957 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 { 958 {
864 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) 959 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
865 { 960 {
866 // These exceptions here will cause a lot of complaints from the users specifically because 961 // These exceptions here will cause a lot of complaints from the users specifically because
867 // they happen every time at border crossings 962 // they happen every time at border crossings
868 if (returnNullIfLandObjectOutsideBounds) 963 if (returnNullIfLandObjectOutsideBounds)
869 return null; 964 return null;
870 else 965 else
871 throw new Exception( 966 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}",
873 LogHeader, m_scene.RegionInfo.RegionName, x, y)
874 );
875 } 967 }
876 968
877 return m_landList[m_landIDList[x / 4, y / 4]]; 969 if(m_landList.Count == 0 || m_landIDList == null)
970 return null;
971
972 lock (m_landIDList)
973 {
974 try
975 {
976 return m_landList[m_landIDList[x / 4, y / 4]];
977 }
978 catch (IndexOutOfRangeException)
979 {
980 return null;
981 }
982 }
878 } 983 }
879 984
880 // Create a 'parcel is here' bitmap for the parcel identified by the passed landID 985 // Create a 'parcel is here' bitmap for the parcel identified by the passed landID
@@ -926,7 +1031,7 @@ namespace OpenSim.Region.CoreModules.World.Land
926 } 1031 }
927 } 1032 }
928 1033
929 public void FinalizeLandPrimCountUpdate() 1034 private void FinalizeLandPrimCountUpdate()
930 { 1035 {
931 //Get Simwide prim count for owner 1036 //Get Simwide prim count for owner
932 Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>(); 1037 Dictionary<UUID, List<LandObject>> landOwnersAndParcels = new Dictionary<UUID, List<LandObject>>();
@@ -967,10 +1072,10 @@ namespace OpenSim.Region.CoreModules.World.Land
967 1072
968 public void EventManagerOnParcelPrimCountUpdate() 1073 public void EventManagerOnParcelPrimCountUpdate()
969 { 1074 {
970// m_log.DebugFormat( 1075 //m_log.DebugFormat(
971// "[LAND MANAGEMENT MODULE]: Triggered EventManagerOnParcelPrimCountUpdate() for {0}", 1076 // "[land management module]: triggered eventmanageronparcelprimcountupdate() for {0}",
972// m_scene.RegionInfo.RegionName); 1077 // m_scene.RegionInfo.RegionName);
973 1078
974 ResetOverMeRecords(); 1079 ResetOverMeRecords();
975 EntityBase[] entities = m_scene.Entities.GetEntities(); 1080 EntityBase[] entities = m_scene.Entities.GetEntities();
976 foreach (EntityBase obj in entities) 1081 foreach (EntityBase obj in entities)
@@ -1002,27 +1107,33 @@ namespace OpenSim.Region.CoreModules.World.Land
1002 /// <param name="end_y">North Point</param> 1107 /// <param name="end_y">North Point</param>
1003 /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param> 1108 /// <param name="attempting_user_id">UUID of user who is trying to subdivide</param>
1004 /// <returns>Returns true if successful</returns> 1109 /// <returns>Returns true if successful</returns>
1005 private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) 1110 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
1006 { 1111 {
1007 //First, lets loop through the points and make sure they are all in the same peice of land 1112 //First, lets loop through the points and make sure they are all in the same peice of land
1008 //Get the land object at start 1113 //Get the land object at start
1009 1114
1010 ILandObject startLandObject = GetLandObject(start_x, start_y); 1115 ILandObject startLandObject = GetLandObject(start_x, start_y);
1011 1116
1012 if (startLandObject == null) return; 1117 if (startLandObject == null)
1118 return;
1119
1120 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin, true))
1121 {
1122 return;
1123 }
1013 1124
1014 //Loop through the points 1125 //Loop through the points
1015 try 1126 try
1016 { 1127 {
1017 int totalX = end_x - start_x; 1128 for (int y = start_y; y < end_y; y++)
1018 int totalY = end_y - start_y;
1019 for (int y = 0; y < totalY; y++)
1020 { 1129 {
1021 for (int x = 0; x < totalX; x++) 1130 for (int x = start_x; x < end_x; x++)
1022 { 1131 {
1023 ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y); 1132 ILandObject tempLandObject = GetLandObject(x, y);
1024 if (tempLandObject == null) return; 1133 if (tempLandObject == null)
1025 if (tempLandObject != startLandObject) return; 1134 return;
1135 if (tempLandObject != startLandObject)
1136 return;
1026 } 1137 }
1027 } 1138 }
1028 } 1139 }
@@ -1031,22 +1142,22 @@ namespace OpenSim.Region.CoreModules.World.Land
1031 return; 1142 return;
1032 } 1143 }
1033 1144
1034 //If we are still here, then they are subdividing within one piece of land 1145 //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
1035 //Check owner
1036 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin))
1037 {
1038 return;
1039 }
1040
1041 //Lets create a new land object with bitmap activated at that point (keeping the old land objects info)
1042 ILandObject newLand = startLandObject.Copy(); 1146 ILandObject newLand = startLandObject.Copy();
1147
1043 newLand.LandData.Name = newLand.LandData.Name; 1148 newLand.LandData.Name = newLand.LandData.Name;
1044 newLand.LandData.GlobalID = UUID.Random(); 1149 newLand.LandData.GlobalID = UUID.Random();
1045 newLand.LandData.Dwell = 0; 1150 newLand.LandData.Dwell = 0;
1151 // Clear "Show in search" on the cut out parcel to prevent double-charging
1152 newLand.LandData.Flags &= ~(uint)ParcelFlags.ShowDirectory;
1153 // invalidate landing point
1154 newLand.LandData.LandingType = (byte)LandingType.Direct;
1155 newLand.LandData.UserLocation = Vector3.Zero;
1156 newLand.LandData.UserLookAt = Vector3.Zero;
1046 1157
1047 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 1158 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
1048 1159
1049 //Now, lets set the subdivision area of the original to false 1160 //lets set the subdivision area of the original to false
1050 int startLandObjectIndex = startLandObject.LandData.LocalID; 1161 int startLandObjectIndex = startLandObject.LandData.LocalID;
1051 lock (m_landList) 1162 lock (m_landList)
1052 { 1163 {
@@ -1055,65 +1166,85 @@ namespace OpenSim.Region.CoreModules.World.Land
1055 m_landList[startLandObjectIndex].ForceUpdateLandInfo(); 1166 m_landList[startLandObjectIndex].ForceUpdateLandInfo();
1056 } 1167 }
1057 1168
1058 //Now add the new land object 1169 //add the new land object
1059 ILandObject result = AddLandObject(newLand); 1170 ILandObject result = AddLandObject(newLand);
1060 1171
1061 if (result != null) 1172 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData);
1173
1174 if(startLandObject.LandData.LandingType == (byte)LandingType.LandingPoint)
1062 { 1175 {
1063 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); 1176 int x = (int)startLandObject.LandData.UserLocation.X;
1064 result.SendLandUpdateToAvatarsOverMe(); 1177 int y = (int)startLandObject.LandData.UserLocation.Y;
1065 } 1178 if(!startLandObject.ContainsPoint(x, y))
1179 {
1180 startLandObject.LandData.LandingType = (byte)LandingType.Direct;
1181 startLandObject.LandData.UserLocation = Vector3.Zero;
1182 startLandObject.LandData.UserLookAt = Vector3.Zero;
1183 }
1184 }
1185
1186 m_scene.EventManager.TriggerParcelPrimCountTainted();
1187
1188 result.SendLandUpdateToAvatarsOverMe();
1189 startLandObject.SendLandUpdateToAvatarsOverMe();
1190 m_scene.ForEachClient(SendParcelOverlay);
1191
1066 } 1192 }
1067 1193
1068 /// <summary> 1194 /// <summary>
1069 /// Join 2 land objects together 1195 /// Join 2 land objects together
1070 /// </summary> 1196 /// </summary>
1071 /// <param name="start_x">x value in first piece of land</param> 1197 /// <param name="start_x">start x of selection area</param>
1072 /// <param name="start_y">y value in first piece of land</param> 1198 /// <param name="start_y">start y of selection area</param>
1073 /// <param name="end_x">x value in second peice of land</param> 1199 /// <param name="end_x">end x of selection area</param>
1074 /// <param name="end_y">y value in second peice of land</param> 1200 /// <param name="end_y">end y of selection area</param>
1075 /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param> 1201 /// <param name="attempting_user_id">UUID of the avatar trying to join the land objects</param>
1076 /// <returns>Returns true if successful</returns> 1202 /// <returns>Returns true if successful</returns>
1077 private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) 1203 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
1078 { 1204 {
1079 end_x -= 4; 1205 int index = 0;
1080 end_y -= 4; 1206 int maxindex = -1;
1207 int maxArea = 0;
1081 1208
1082 List<ILandObject> selectedLandObjects = new List<ILandObject>(); 1209 List<ILandObject> selectedLandObjects = new List<ILandObject>();
1083 int stepYSelected; 1210 for (int x = start_x; x < end_x; x += 4)
1084 for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4)
1085 { 1211 {
1086 int stepXSelected; 1212 for (int y = start_y; y < end_y; y += 4)
1087 for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4)
1088 { 1213 {
1089 ILandObject p = GetLandObject(stepXSelected, stepYSelected); 1214 ILandObject p = GetLandObject(x, y);
1090 1215
1091 if (p != null) 1216 if (p != null)
1092 { 1217 {
1093 if (!selectedLandObjects.Contains(p)) 1218 if (!selectedLandObjects.Contains(p))
1094 { 1219 {
1095 selectedLandObjects.Add(p); 1220 selectedLandObjects.Add(p);
1221 if(p.LandData.Area > maxArea)
1222 {
1223 maxArea = p.LandData.Area;
1224 maxindex = index;
1225 }
1226 index++;
1096 } 1227 }
1097 } 1228 }
1098 } 1229 }
1099 } 1230 }
1100 ILandObject masterLandObject = selectedLandObjects[0];
1101 selectedLandObjects.RemoveAt(0);
1102 1231
1103 if (selectedLandObjects.Count < 1) 1232 if(maxindex < 0 || selectedLandObjects.Count < 2)
1104 {
1105 return; 1233 return;
1106 } 1234
1107 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin)) 1235 ILandObject masterLandObject = selectedLandObjects[maxindex];
1236 selectedLandObjects.RemoveAt(maxindex);
1237
1238 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin, true))
1108 { 1239 {
1109 return; 1240 return;
1110 } 1241 }
1242
1243 UUID masterOwner = masterLandObject.LandData.OwnerID;
1111 foreach (ILandObject p in selectedLandObjects) 1244 foreach (ILandObject p in selectedLandObjects)
1112 { 1245 {
1113 if (p.LandData.OwnerID != masterLandObject.LandData.OwnerID) 1246 if (p.LandData.OwnerID != masterOwner)
1114 {
1115 return; 1247 return;
1116 }
1117 } 1248 }
1118 1249
1119 lock (m_landList) 1250 lock (m_landList)
@@ -1126,29 +1257,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1126 } 1257 }
1127 } 1258 }
1128 1259
1260 m_scene.EventManager.TriggerParcelPrimCountTainted();
1129 masterLandObject.SendLandUpdateToAvatarsOverMe(); 1261 masterLandObject.SendLandUpdateToAvatarsOverMe();
1262 m_scene.ForEachClient(SendParcelOverlay);
1130 } 1263 }
1131
1132 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
1133 {
1134 join(start_x, start_y, end_x, end_y, attempting_user_id);
1135 }
1136
1137 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
1138 {
1139 subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
1140 }
1141
1142 #endregion 1264 #endregion
1143 1265
1144 #region Parcel Updating 1266 #region Parcel Updating
1145 1267
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> 1268 /// <summary>
1153 /// Send the parcel overlay blocks to the client. We send the overlay packets 1269 /// Send the parcel overlay blocks to the client. We send the overlay packets
1154 /// around a location and limited by the 'parcelLayerViewDistance'. This number 1270 /// around a location and limited by the 'parcelLayerViewDistance'. This number
@@ -1162,145 +1278,115 @@ namespace OpenSim.Region.CoreModules.World.Land
1162 /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param> 1278 /// <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> 1279 /// <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> 1280 /// <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) 1281 public void SendParcelOverlay(IClientAPI remote_client)
1166 { 1282 {
1283 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
1284 return;
1285
1167 const int LAND_BLOCKS_PER_PACKET = 1024; 1286 const int LAND_BLOCKS_PER_PACKET = 1024;
1168 1287
1169 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1288 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1170 int byteArrayCount = 0; 1289 int byteArrayCount = 0;
1171 int sequenceID = 0; 1290 int sequenceID = 0;
1172 1291
1173 int xLow = 0; 1292 // Layer data is in LandUnit (4m) chunks
1174 int xHigh = (int)m_scene.RegionInfo.RegionSizeX; 1293 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 { 1294 {
1180 // Compute view distance around the given point 1295 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 { 1296 {
1186 txLow = xLow; 1297 byte tempByte = 0; //This represents the byte for the current 4x4
1187 txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh);
1188 }
1189 if (txHigh > xHigh)
1190 {
1191 txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2));
1192 txHigh = xHigh;
1193 }
1194 xLow = txLow;
1195 xHigh = txHigh;
1196 1298
1197 int tyLow = yPlace - layerViewDistance; 1299 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 1300
1215 // Layer data is in landUnit (4m) chunks 1301 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 { 1302 {
1224 // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); 1303 // types
1225 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1304 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
1226 byteArrayCount = 0; 1305 {
1227 sequenceID++; 1306 //Owner Flag
1228 byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1307 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER;
1229 } 1308 }
1309 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1310 {
1311 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP;
1312 }
1313 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1314 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1315 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1316 {
1317 //Sale type
1318 tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE;
1319 }
1320 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1321 {
1322 //Public type
1323 tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero
1324 }
1325 // LAND_TYPE_IS_BEING_AUCTIONED still unsuported
1326 else
1327 {
1328 //Other Flag
1329 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER;
1330 }
1230 1331
1231 } 1332 // now flags
1232 } 1333 // border control
1233 1334
1234 if (byteArrayCount != 0) 1335 ILandObject westParcel = null;
1235 { 1336 ILandObject southParcel = null;
1236 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1337 if (x > 0)
1237 // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); 1338 {
1238 } 1339 westParcel = GetLandObject((x - 1), y);
1239 } 1340 }
1341 if (y > 0)
1342 {
1343 southParcel = GetLandObject(x, (y - 1));
1344 }
1240 1345
1241 private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client) 1346 if (x == 0)
1242 { 1347 {
1243 byte tempByte = 0; //This represents the byte for the current 4x4 1348 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1349 }
1350 else if (westParcel != null && westParcel != currentParcelBlock)
1351 {
1352 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1353 }
1244 1354
1245 if (currentParcelBlock != null) 1355 if (y == 0)
1246 { 1356 {
1247 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) 1357 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1248 { 1358 }
1249 //Owner Flag 1359 else if (southParcel != null && southParcel != currentParcelBlock)
1250 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1360 {
1251 } 1361 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1252 else if (currentParcelBlock.LandData.SalePrice > 0 && 1362 }
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 1363
1270 //Now for border control 1364 // local sound
1365 if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0)
1366 tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND;
1271 1367
1272 ILandObject westParcel = null; 1368 // hide avatars
1273 ILandObject southParcel = null; 1369 if (!currentParcelBlock.LandData.SeeAVs)
1274 if (x > 0) 1370 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 1371
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 1372
1292 if (y == 0) 1373 byteArray[byteArrayCount] = tempByte;
1293 { 1374 byteArrayCount++;
1294 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1375 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1295 } 1376 {
1296 else if (southParcel != null && southParcel != currentParcelBlock) 1377 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1297 { 1378 byteArrayCount = 0;
1298 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1379 sequenceID++;
1380 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1381 }
1382 }
1299 } 1383 }
1300
1301 } 1384 }
1302 1385
1303 return tempByte; 1386 if (byteArrayCount > 0)
1387 {
1388 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1389 }
1304 } 1390 }
1305 1391
1306 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, 1392 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
@@ -1320,8 +1406,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1320 { 1406 {
1321 if (!temp.Contains(currentParcel)) 1407 if (!temp.Contains(currentParcel))
1322 { 1408 {
1323 currentParcel.ForceUpdateLandInfo(); 1409 if (!currentParcel.IsBannedFromLand(remote_client.AgentId))
1324 temp.Add(currentParcel); 1410 {
1411 currentParcel.ForceUpdateLandInfo();
1412 temp.Add(currentParcel);
1413 }
1325 } 1414 }
1326 } 1415 }
1327 } 1416 }
@@ -1338,8 +1427,44 @@ namespace OpenSim.Region.CoreModules.World.Land
1338 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); 1427 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
1339 } 1428 }
1340 1429
1341 // Also send the layer data around the point of interest 1430// SendParcelOverlay(remote_client);
1342 SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance); 1431 }
1432
1433 public void UpdateLandProperties(ILandObject land, LandUpdateArgs args, IClientAPI remote_client)
1434 {
1435 bool snap_selection = false;
1436 bool needOverlay = false;
1437 if (land.UpdateLandProperties(args, remote_client, out snap_selection, out needOverlay))
1438 {
1439 UUID parcelID = land.LandData.GlobalID;
1440 m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
1441 {
1442 if (avatar.IsDeleted || avatar.IsNPC)
1443 return;
1444
1445 IClientAPI client = avatar.ControllingClient;
1446 if (needOverlay)
1447 SendParcelOverlay(client);
1448
1449 if (avatar.IsChildAgent)
1450 {
1451 if(client == remote_client)
1452 land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client);
1453 return;
1454 }
1455
1456 ILandObject aland = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
1457 if (aland != null)
1458 {
1459 if(client == remote_client && land != aland)
1460 land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, client);
1461 else if (land == aland)
1462 aland.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, client);
1463 }
1464 if (avatar.currentParcelUUID == parcelID)
1465 avatar.currentParcelUUID = parcelID; // force parcel flags review
1466 });
1467 }
1343 } 1468 }
1344 1469
1345 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) 1470 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
@@ -1352,19 +1477,19 @@ namespace OpenSim.Region.CoreModules.World.Land
1352 1477
1353 if (land != null) 1478 if (land != null)
1354 { 1479 {
1355 land.UpdateLandProperties(args, remote_client); 1480 UpdateLandProperties(land, args, remote_client);
1356 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); 1481 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client);
1357 } 1482 }
1358 } 1483 }
1359 1484
1360 public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) 1485 public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client)
1361 { 1486 {
1362 subdivide(west, south, east, north, remote_client.AgentId); 1487 Subdivide(west, south, east, north, remote_client.AgentId);
1363 } 1488 }
1364 1489
1365 public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) 1490 public void ClientOnParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client)
1366 { 1491 {
1367 join(west, south, east, north, remote_client.AgentId); 1492 Join(west, south, east, north, remote_client.AgentId);
1368 } 1493 }
1369 1494
1370 public void ClientOnParcelSelectObjects(int local_id, int request_type, 1495 public void ClientOnParcelSelectObjects(int local_id, int request_type,
@@ -1375,7 +1500,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1375 1500
1376 public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client) 1501 public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client)
1377 { 1502 {
1378 ILandObject land; 1503 ILandObject land = null;
1379 lock (m_landList) 1504 lock (m_landList)
1380 { 1505 {
1381 m_landList.TryGetValue(local_id, out land); 1506 m_landList.TryGetValue(local_id, out land);
@@ -1384,7 +1509,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1384 if (land != null) 1509 if (land != null)
1385 { 1510 {
1386 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 1511 m_scene.EventManager.TriggerParcelPrimCountUpdate();
1387 m_landList[local_id].SendLandObjectOwners(remote_client); 1512 land.SendLandObjectOwners(remote_client);
1388 } 1513 }
1389 else 1514 else
1390 { 1515 {
@@ -1394,7 +1519,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1394 1519
1395 public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client) 1520 public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client)
1396 { 1521 {
1397 ILandObject land; 1522 ILandObject land = null;
1398 lock (m_landList) 1523 lock (m_landList)
1399 { 1524 {
1400 m_landList.TryGetValue(local_id, out land); 1525 m_landList.TryGetValue(local_id, out land);
@@ -1408,7 +1533,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1408 land.LandData.GroupID = UUID.Zero; 1533 land.LandData.GroupID = UUID.Zero;
1409 land.LandData.IsGroupOwned = false; 1534 land.LandData.IsGroupOwned = false;
1410 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1535 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1411
1412 m_scene.ForEachClient(SendParcelOverlay); 1536 m_scene.ForEachClient(SendParcelOverlay);
1413 land.SendLandUpdateToClient(true, remote_client); 1537 land.SendLandUpdateToClient(true, remote_client);
1414 UpdateLandObject(land.LandData.LocalID, land.LandData); 1538 UpdateLandObject(land.LandData.LocalID, land.LandData);
@@ -1418,7 +1542,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1418 1542
1419 public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client) 1543 public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client)
1420 { 1544 {
1421 ILandObject land; 1545 ILandObject land = null;
1422 lock (m_landList) 1546 lock (m_landList)
1423 { 1547 {
1424 m_landList.TryGetValue(local_id, out land); 1548 m_landList.TryGetValue(local_id, out land);
@@ -1432,7 +1556,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1432 land.LandData.GroupID = UUID.Zero; 1556 land.LandData.GroupID = UUID.Zero;
1433 land.LandData.IsGroupOwned = false; 1557 land.LandData.IsGroupOwned = false;
1434 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1558 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1435 1559
1436 m_scene.ForEachClient(SendParcelOverlay); 1560 m_scene.ForEachClient(SendParcelOverlay);
1437 land.SendLandUpdateToClient(true, remote_client); 1561 land.SendLandUpdateToClient(true, remote_client);
1438 UpdateLandObject(land.LandData.LocalID, land.LandData); 1562 UpdateLandObject(land.LandData.LocalID, land.LandData);
@@ -1442,7 +1566,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1442 1566
1443 public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client) 1567 public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client)
1444 { 1568 {
1445 ILandObject land; 1569 ILandObject land = null;
1446 lock (m_landList) 1570 lock (m_landList)
1447 { 1571 {
1448 m_landList.TryGetValue(local_id, out land); 1572 m_landList.TryGetValue(local_id, out land);
@@ -1458,8 +1582,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1458 land.LandData.IsGroupOwned = false; 1582 land.LandData.IsGroupOwned = false;
1459 land.LandData.SalePrice = 0; 1583 land.LandData.SalePrice = 0;
1460 land.LandData.AuthBuyerID = UUID.Zero; 1584 land.LandData.AuthBuyerID = UUID.Zero;
1585 land.LandData.SeeAVs = true;
1586 land.LandData.AnyAVSounds = true;
1587 land.LandData.GroupAVSounds = true;
1461 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1588 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1462
1463 m_scene.ForEachClient(SendParcelOverlay); 1589 m_scene.ForEachClient(SendParcelOverlay);
1464 land.SendLandUpdateToClient(true, remote_client); 1590 land.SendLandUpdateToClient(true, remote_client);
1465 UpdateLandObject(land.LandData.LocalID, land.LandData); 1591 UpdateLandObject(land.LandData.LocalID, land.LandData);
@@ -1526,17 +1652,16 @@ namespace OpenSim.Region.CoreModules.World.Land
1526 1652
1527 void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client) 1653 void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client)
1528 { 1654 {
1529 ILandObject land; 1655 ILandObject land = null;
1530 lock (m_landList) 1656 lock (m_landList)
1531 { 1657 {
1532 m_landList.TryGetValue(parcelLocalID, out land); 1658 m_landList.TryGetValue(parcelLocalID, out land);
1533 } 1659 }
1534 1660
1535 if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land))
1536 return;
1537
1538 if (land != null) 1661 if (land != null)
1539 { 1662 {
1663 if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land))
1664 return;
1540 land.DeedToGroup(groupID); 1665 land.DeedToGroup(groupID);
1541 } 1666 }
1542 } 1667 }
@@ -1545,17 +1670,12 @@ namespace OpenSim.Region.CoreModules.World.Land
1545 1670
1546 private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1671 private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1547 { 1672 {
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) 1673 lock (m_landList)
1554 { 1674 {
1555 for (int i = 0; i < data.Count; i++) 1675 for (int i = 0; i < data.Count; i++)
1556 IncomingLandObjectFromStorage(data[i]); 1676 IncomingLandObjectFromStorage(data[i]);
1557 1677
1558 // Layer data is in landUnit (4m) chunks 1678 // Layer data is in LandUnit (4m) chunks
1559 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) 1679 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1560 { 1680 {
1561 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) 1681 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
@@ -1565,7 +1685,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1565 if (m_landList.Count == 1) 1685 if (m_landList.Count == 1)
1566 { 1686 {
1567 m_log.DebugFormat( 1687 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}", 1688 "[{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); 1689 LogHeader, x, y, m_scene.Name);
1570 1690
1571 int onlyParcelID = 0; 1691 int onlyParcelID = 0;
@@ -1588,11 +1708,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1588 else if (m_landList.Count > 1) 1708 else if (m_landList.Count > 1)
1589 { 1709 {
1590 m_log.DebugFormat( 1710 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}", 1711 "{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); 1712 LogHeader, x, y, m_scene.Name);
1593 1713
1594 // There are several other parcels so we must create a new one for the unassigned space 1714 // 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); 1715 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
1596 // Claim all the unclaimed "0" ids 1716 // Claim all the unclaimed "0" ids
1597 newLand.SetLandBitmap(CreateBitmapForID(0)); 1717 newLand.SetLandBitmap(CreateBitmapForID(0));
1598 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 1718 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
@@ -1603,20 +1723,23 @@ namespace OpenSim.Region.CoreModules.World.Land
1603 { 1723 {
1604 // We should never reach this point as the separate code path when no land data exists should have fired instead. 1724 // We should never reach this point as the separate code path when no land data exists should have fired instead.
1605 m_log.WarnFormat( 1725 m_log.WarnFormat(
1606 "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", 1726 "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present",
1607 LogHeader, m_scene.Name); 1727 LogHeader, m_scene.Name);
1608 } 1728 }
1609 } 1729 }
1610 } 1730 }
1611 } 1731 }
1732 FinalizeLandPrimCountUpdate(); // update simarea information
1612 } 1733 }
1613 } 1734 }
1614 1735
1615 private void IncomingLandObjectFromStorage(LandData data) 1736 private void IncomingLandObjectFromStorage(LandData data)
1616 { 1737 {
1617 ILandObject new_land = new LandObject(data, m_scene); 1738 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene, data);
1618 new_land.SetLandBitmapFromByteArray(); 1739
1740 new_land.SetLandBitmapFromByteArray();
1619 AddLandObject(new_land); 1741 AddLandObject(new_land);
1742// new_land.SendLandUpdateToAvatarsOverMe();
1620 } 1743 }
1621 1744
1622 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1745 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
@@ -1629,7 +1752,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1629 m_landList.TryGetValue(localID, out selectedParcel); 1752 m_landList.TryGetValue(localID, out selectedParcel);
1630 } 1753 }
1631 1754
1632 if (selectedParcel == null) 1755 if (selectedParcel == null)
1633 return; 1756 return;
1634 1757
1635 selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient); 1758 selectedParcel.ReturnLandObjects(returnType, agentIDs, taskIDs, remoteClient);
@@ -1670,9 +1793,9 @@ namespace OpenSim.Region.CoreModules.World.Land
1670 foreach (HashSet<SceneObjectGroup> objs in returns.Values) 1793 foreach (HashSet<SceneObjectGroup> objs in returns.Values)
1671 { 1794 {
1672 List<SceneObjectGroup> objs2 = new List<SceneObjectGroup>(objs); 1795 List<SceneObjectGroup> objs2 = new List<SceneObjectGroup>(objs);
1673 if (m_scene.Permissions.CanReturnObjects(null, remoteClient.AgentId, objs2)) 1796 if (m_scene.Permissions.CanReturnObjects(null, remoteClient, objs2))
1674 { 1797 {
1675 m_scene.returnObjects(objs2.ToArray(), remoteClient.AgentId); 1798 m_scene.returnObjects(objs2.ToArray(), remoteClient);
1676 } 1799 }
1677 else 1800 else
1678 { 1801 {
@@ -1710,12 +1833,13 @@ namespace OpenSim.Region.CoreModules.World.Land
1710 1833
1711 private void EventManagerOnRegisterCaps(UUID agentID, Caps caps) 1834 private void EventManagerOnRegisterCaps(UUID agentID, Caps caps)
1712 { 1835 {
1836 //string capsBase = "/CAPS/" + UUID.Random();
1713 string capsBase = "/CAPS/" + caps.CapsObjectPath; 1837 string capsBase = "/CAPS/" + caps.CapsObjectPath;
1714 caps.RegisterHandler( 1838 caps.RegisterHandler(
1715 "RemoteParcelRequest", 1839 "RemoteParcelRequest",
1716 new RestStreamHandler( 1840 new RestStreamHandler(
1717 "POST", 1841 "POST",
1718 capsBase + remoteParcelRequestPath, 1842 capsBase,
1719 (request, path, param, httpRequest, httpResponse) 1843 (request, path, param, httpRequest, httpResponse)
1720 => RemoteParcelRequest(request, path, param, agentID, caps), 1844 => RemoteParcelRequest(request, path, param, agentID, caps),
1721 "RemoteParcelRequest", 1845 "RemoteParcelRequest",
@@ -1735,7 +1859,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1735 private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps) 1859 private string ProcessPropertiesUpdate(string request, string path, string param, UUID agentID, Caps caps)
1736 { 1860 {
1737 IClientAPI client; 1861 IClientAPI client;
1738 if (!m_scene.TryGetClient(agentID, out client)) 1862 if (!m_scene.TryGetClient(agentID, out client))
1739 { 1863 {
1740 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID); 1864 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID);
1741 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1865 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
@@ -1759,7 +1883,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1759 land_update.MusicURL = properties.MusicURL; 1883 land_update.MusicURL = properties.MusicURL;
1760 land_update.Name = properties.Name; 1884 land_update.Name = properties.Name;
1761 land_update.ParcelFlags = (uint) properties.ParcelFlags; 1885 land_update.ParcelFlags = (uint) properties.ParcelFlags;
1762 land_update.PassHours = (int) properties.PassHours; 1886 land_update.PassHours = properties.PassHours;
1763 land_update.PassPrice = (int) properties.PassPrice; 1887 land_update.PassPrice = (int) properties.PassPrice;
1764 land_update.SalePrice = (int) properties.SalePrice; 1888 land_update.SalePrice = (int) properties.SalePrice;
1765 land_update.SnapshotID = properties.SnapshotID; 1889 land_update.SnapshotID = properties.SnapshotID;
@@ -1773,7 +1897,20 @@ namespace OpenSim.Region.CoreModules.World.Land
1773 land_update.ObscureMusic = properties.ObscureMusic; 1897 land_update.ObscureMusic = properties.ObscureMusic;
1774 land_update.ObscureMedia = properties.ObscureMedia; 1898 land_update.ObscureMedia = properties.ObscureMedia;
1775 1899
1776 ILandObject land; 1900 if (args.ContainsKey("see_avs"))
1901 {
1902 land_update.SeeAVs = args["see_avs"].AsBoolean();
1903 land_update.AnyAVSounds = args["any_av_sounds"].AsBoolean();
1904 land_update.GroupAVSounds = args["group_av_sounds"].AsBoolean();
1905 }
1906 else
1907 {
1908 land_update.SeeAVs = true;
1909 land_update.AnyAVSounds = true;
1910 land_update.GroupAVSounds = true;
1911 }
1912
1913 ILandObject land = null;
1777 lock (m_landList) 1914 lock (m_landList)
1778 { 1915 {
1779 m_landList.TryGetValue(parcelID, out land); 1916 m_landList.TryGetValue(parcelID, out land);
@@ -1781,13 +1918,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1781 1918
1782 if (land != null) 1919 if (land != null)
1783 { 1920 {
1784 land.UpdateLandProperties(land_update, client); 1921 UpdateLandProperties(land,land_update, client);
1785 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); 1922 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client);
1786 } 1923 }
1787 else 1924 else
1788 { 1925 {
1789 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); 1926 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID);
1790 } 1927 }
1928
1791 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1929 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1792 } 1930 }
1793 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the 1931 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
@@ -1815,9 +1953,9 @@ namespace OpenSim.Region.CoreModules.World.Land
1815 { 1953 {
1816 Hashtable hash = new Hashtable(); 1954 Hashtable hash = new Hashtable();
1817 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); 1955 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
1818 if (hash.ContainsKey("region_id") && hash.ContainsKey("location")) 1956 if (hash.ContainsKey("location"))
1819 { 1957 {
1820 UUID regionID = (UUID)hash["region_id"]; 1958 UUID scope = m_scene.RegionInfo.ScopeID;
1821 ArrayList list = (ArrayList)hash["location"]; 1959 ArrayList list = (ArrayList)hash["location"];
1822 uint x = (uint)(double)list[0]; 1960 uint x = (uint)(double)list[0];
1823 uint y = (uint)(double)list[1]; 1961 uint y = (uint)(double)list[1];
@@ -1826,19 +1964,46 @@ namespace OpenSim.Region.CoreModules.World.Land
1826 // if you do a "About Landmark" on a landmark a second time, the viewer sends the 1964 // if you do a "About Landmark" on a landmark a second time, the viewer sends the
1827 // region_handle it got earlier via RegionHandleRequest 1965 // region_handle it got earlier via RegionHandleRequest
1828 ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]); 1966 ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]);
1829 parcelID = Util.BuildFakeParcelID(regionHandle, x, y); 1967 if(regionHandle == m_scene.RegionInfo.RegionHandle)
1968 parcelID = Util.BuildFakeParcelID(regionHandle, x, y);
1969 else
1970 {
1971 uint wx;
1972 uint wy;
1973 Util.RegionHandleToWorldLoc(regionHandle, out wx, out wy);
1974 GridRegion info = m_scene.GridService.GetRegionByPosition(scope, (int)wx, (int)wy);
1975 if(info != null)
1976 {
1977 wx -= (uint)info.RegionLocX;
1978 wy -= (uint)info.RegionLocY;
1979 wx += x;
1980 wy += y;
1981 // Firestorm devs have no ideia how to do handlers math
1982 // on all cases
1983 if(wx > info.RegionSizeX || wy > info.RegionSizeY)
1984 {
1985 wx = x;
1986 wy = y;
1987 }
1988 parcelID = Util.BuildFakeParcelID(info.RegionHandle, wx, wy);
1989 }
1990 }
1830 } 1991 }
1831 else if (regionID == m_scene.RegionInfo.RegionID) 1992 else if(hash.ContainsKey("region_id"))
1832 { 1993 {
1994 UUID regionID = (UUID)hash["region_id"];
1995 if (regionID == m_scene.RegionInfo.RegionID)
1996 {
1833 // a parcel request for a local parcel => no need to query the grid 1997 // a parcel request for a local parcel => no need to query the grid
1834 parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y); 1998 parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y);
1835 } 1999 }
1836 else 2000 else
1837 { 2001 {
1838 // a parcel request for a parcel in another region. Ask the grid about the region 2002 // a parcel request for a parcel in another region. Ask the grid about the region
1839 GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, regionID); 2003 GridRegion info = m_scene.GridService.GetRegionByUUID(scope, regionID);
1840 if (info != null) 2004 if (info != null)
1841 parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y); 2005 parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
2006 }
1842 } 2007 }
1843 } 2008 }
1844 } 2009 }
@@ -1854,7 +2019,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1854 2019
1855 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); 2020 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse();
1856 response.parcel_id = parcelID; 2021 response.parcel_id = parcelID;
1857 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID); 2022 //m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID);
1858 2023
1859 return LLSDHelpers.SerialiseLLSDReply(response); 2024 return LLSDHelpers.SerialiseLLSDReply(response);
1860 } 2025 }
@@ -1871,17 +2036,25 @@ namespace OpenSim.Region.CoreModules.World.Land
1871 { 2036 {
1872 UUID parcel = UUID.Zero; 2037 UUID parcel = UUID.Zero;
1873 UUID.TryParse(id, out parcel); 2038 UUID.TryParse(id, out parcel);
2039
1874 // assume we've got the parcelID we just computed in RemoteParcelRequest 2040 // assume we've got the parcelID we just computed in RemoteParcelRequest
1875 ExtendedLandData extLandData = new ExtendedLandData(); 2041 ExtendedLandData extLandData = new ExtendedLandData();
1876 Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, 2042 if(!Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle,
1877 out extLandData.X, out extLandData.Y); 2043 out extLandData.X, out extLandData.Y))
1878 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", 2044 return null;
2045 m_log.DebugFormat("[LAND MANAGEMENT MODULE] : Got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
1879 extLandData.RegionHandle, extLandData.X, extLandData.Y); 2046 extLandData.RegionHandle, extLandData.X, extLandData.Y);
1880 2047
1881 // for this region or for somewhere else? 2048 // for this region or for somewhere else?
1882 if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle) 2049 if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle)
1883 { 2050 {
1884 extLandData.LandData = this.GetLandObject(extLandData.X, extLandData.Y).LandData; 2051 ILandObject extLandObject = this.GetLandObject(extLandData.X, extLandData.Y);
2052 if(extLandObject == null)
2053 {
2054 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: ParcelInfoRequest: a FakeParcelID points to outside the region");
2055 return null;
2056 }
2057 extLandData.LandData = extLandObject.LandData;
1885 extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel; 2058 extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel;
1886 } 2059 }
1887 else 2060 else
@@ -1907,6 +2080,9 @@ namespace OpenSim.Region.CoreModules.World.Land
1907 if (data.RegionHandle == m_scene.RegionInfo.RegionHandle) 2080 if (data.RegionHandle == m_scene.RegionInfo.RegionHandle)
1908 { 2081 {
1909 info = new GridRegion(m_scene.RegionInfo); 2082 info = new GridRegion(m_scene.RegionInfo);
2083 IDwellModule dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
2084 if (dwellModule != null)
2085 data.LandData.Dwell = dwellModule.GetDwell(data.LandData);
1910 } 2086 }
1911 else 2087 else
1912 { 2088 {
@@ -1932,7 +2108,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1932 2108
1933 public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) 2109 public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
1934 { 2110 {
1935 ILandObject land; 2111 ILandObject land = null;
1936 lock (m_landList) 2112 lock (m_landList)
1937 { 2113 {
1938 m_landList.TryGetValue(localID, out land); 2114 m_landList.TryGetValue(localID, out land);
@@ -1940,14 +2116,91 @@ namespace OpenSim.Region.CoreModules.World.Land
1940 2116
1941 if (land == null) return; 2117 if (land == null) return;
1942 2118
1943 if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions)) 2119 if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions, false))
1944 return; 2120 return;
1945 2121
1946 land.LandData.OtherCleanTime = otherCleanTime; 2122 land.LandData.OtherCleanTime = otherCleanTime;
1947 2123
1948 UpdateLandObject(localID, land.LandData); 2124 UpdateLandObject(localID, land.LandData);
1949 } 2125 }
1950 2126
2127 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
2128 {
2129 ILandObject land = null;
2130 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
2131 foreach (ILandObject landObject in Land)
2132 {
2133 if (landObject.LandData.LocalID == landID)
2134 {
2135 land = landObject;
2136 }
2137 }
2138 land.DeedToGroup(DefaultGodParcelGroup);
2139 land.LandData.Name = DefaultGodParcelName;
2140 land.SendLandUpdateToAvatarsOverMe();
2141 }
2142
2143 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
2144 {
2145 ScenePresence SP;
2146 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
2147 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
2148 if (SP.GodController.UserLevel != 0)
2149 {
2150 if (flags == 0) //All parcels, scripted or not
2151 {
2152 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
2153 {
2154 if (e.OwnerID == targetID)
2155 {
2156 returns.Add(e);
2157 }
2158 }
2159 );
2160 }
2161 if (flags == 4) //All parcels, scripted object
2162 {
2163 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
2164 {
2165 if (e.OwnerID == targetID)
2166 {
2167 if (e.ContainsScripts())
2168 {
2169 returns.Add(e);
2170 }
2171 }
2172 });
2173 }
2174 if (flags == 4) //not target parcel, scripted object
2175 {
2176 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
2177 {
2178 if (e.OwnerID == targetID)
2179 {
2180 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
2181 if (landobject.LandData.OwnerID != e.OwnerID)
2182 {
2183 if (e.ContainsScripts())
2184 {
2185 returns.Add(e);
2186 }
2187 }
2188 }
2189 });
2190 }
2191 foreach (SceneObjectGroup ol in returns)
2192 {
2193 ReturnObject(ol, client);
2194 }
2195 }
2196 }
2197 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
2198 {
2199 SceneObjectGroup[] objs = new SceneObjectGroup[1];
2200 objs[0] = obj;
2201 ((Scene)client.Scene).returnObjects(objs, client);
2202 }
2203
1951 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); 2204 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1952 2205
1953 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) 2206 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
@@ -1958,12 +2211,12 @@ namespace OpenSim.Region.CoreModules.World.Land
1958 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager); 2211 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager);
1959 System.Threading.Timer Timer; 2212 System.Threading.Timer Timer;
1960 2213
1961 if (targetAvatar.UserLevel == 0) 2214 if (targetAvatar.GodController.UserLevel < 200)
1962 { 2215 {
1963 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 2216 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)) 2217 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true))
1965 return; 2218 return;
1966 if (flags == 0) 2219 if ((flags & 1) == 0) // only lowest bit has meaning for now
1967 { 2220 {
1968 targetAvatar.AllowMovement = false; 2221 targetAvatar.AllowMovement = false;
1969 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world."); 2222 targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world.");
@@ -1983,7 +2236,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1983 } 2236 }
1984 } 2237 }
1985 } 2238 }
1986
1987 private void OnEndParcelFrozen(object avatar) 2239 private void OnEndParcelFrozen(object avatar)
1988 { 2240 {
1989 ScenePresence targetAvatar = (ScenePresence)avatar; 2241 ScenePresence targetAvatar = (ScenePresence)avatar;
@@ -2010,12 +2262,13 @@ namespace OpenSim.Region.CoreModules.World.Land
2010 2262
2011 // Check if you even have permission to do this 2263 // Check if you even have permission to do this
2012 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 2264 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
2013 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) && 2265 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true) &&
2014 !m_scene.Permissions.IsAdministrator(client.AgentId)) 2266 !m_scene.Permissions.IsAdministrator(client.AgentId))
2015 return; 2267 return;
2268
2016 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); 2269 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
2017 2270
2018 targetAvatar.TeleportWithMomentum(pos, null); 2271 targetAvatar.TeleportOnEject(pos);
2019 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); 2272 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
2020 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); 2273 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
2021 2274
@@ -2059,7 +2312,7 @@ namespace OpenSim.Region.CoreModules.World.Land
2059 if (// Required: local user; foreign users cannot set home 2312 if (// Required: local user; foreign users cannot set home
2060 m_scene.UserManagementModule.IsLocalGridUser(remoteClient.AgentId) && 2313 m_scene.UserManagementModule.IsLocalGridUser(remoteClient.AgentId) &&
2061 (// (a) gods and land managers can set home 2314 (// (a) gods and land managers can set home
2062 m_scene.Permissions.IsAdministrator(remoteClient.AgentId) || 2315 m_scene.Permissions.IsAdministrator(remoteClient.AgentId) ||
2063 m_scene.Permissions.IsGod(remoteClient.AgentId) || 2316 m_scene.Permissions.IsGod(remoteClient.AgentId) ||
2064 // (b) land owners can set home 2317 // (b) land owners can set home
2065 remoteClient.AgentId == land.LandData.OwnerID || 2318 remoteClient.AgentId == land.LandData.OwnerID ||
@@ -2111,8 +2364,8 @@ namespace OpenSim.Region.CoreModules.World.Land
2111 "If no local land ID is given, then summary information about all the parcels is shown.\n" 2364 "If no local land ID is given, then summary information about all the parcels is shown.\n"
2112 + "If a local land ID is given then full information about that parcel is shown.", 2365 + "If a local land ID is given then full information about that parcel is shown.",
2113 HandleShowCommand); 2366 HandleShowCommand);
2114 } 2367 }
2115 2368
2116 protected void HandleClearCommand(string module, string[] args) 2369 protected void HandleClearCommand(string module, string[] args)
2117 { 2370 {
2118 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) 2371 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
@@ -2120,9 +2373,9 @@ namespace OpenSim.Region.CoreModules.World.Land
2120 2373
2121 string response = MainConsole.Instance.CmdPrompt( 2374 string response = MainConsole.Instance.CmdPrompt(
2122 string.Format( 2375 string.Format(
2123 "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name), 2376 "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name),
2124 "n"); 2377 "n");
2125 2378
2126 if (response.ToLower() == "y") 2379 if (response.ToLower() == "y")
2127 { 2380 {
2128 Clear(true); 2381 Clear(true);
@@ -2132,14 +2385,14 @@ namespace OpenSim.Region.CoreModules.World.Land
2132 { 2385 {
2133 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name); 2386 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name);
2134 } 2387 }
2135 } 2388 }
2136 2389
2137 protected void HandleShowCommand(string module, string[] args) 2390 protected void HandleShowCommand(string module, string[] args)
2138 { 2391 {
2139 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) 2392 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
2140 return; 2393 return;
2141 2394
2142 StringBuilder report = new StringBuilder(); 2395 StringBuilder report = new StringBuilder();
2143 2396
2144 if (args.Length <= 2) 2397 if (args.Length <= 2)
2145 { 2398 {
@@ -2152,10 +2405,10 @@ namespace OpenSim.Region.CoreModules.World.Land
2152 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId)) 2405 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId))
2153 return; 2406 return;
2154 2407
2155 ILandObject lo; 2408 ILandObject lo = null;
2156 2409
2157 lock (m_landList) 2410 lock (m_landList)
2158 { 2411 {
2159 if (!m_landList.TryGetValue(landLocalId, out lo)) 2412 if (!m_landList.TryGetValue(landLocalId, out lo))
2160 { 2413 {
2161 MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId); 2414 MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId);
@@ -2170,7 +2423,7 @@ namespace OpenSim.Region.CoreModules.World.Land
2170 } 2423 }
2171 2424
2172 private void AppendParcelsSummaryReport(StringBuilder report) 2425 private void AppendParcelsSummaryReport(StringBuilder report)
2173 { 2426 {
2174 report.AppendFormat("Land information for {0}\n", m_scene.Name); 2427 report.AppendFormat("Land information for {0}\n", m_scene.Name);
2175 2428
2176 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 2429 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
@@ -2180,7 +2433,7 @@ namespace OpenSim.Region.CoreModules.World.Land
2180 cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize); 2433 cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize);
2181 cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize); 2434 cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize);
2182 cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize); 2435 cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize);
2183 2436
2184 lock (m_landList) 2437 lock (m_landList)
2185 { 2438 {
2186 foreach (ILandObject lo in m_landList.Values) 2439 foreach (ILandObject lo in m_landList.Values)
@@ -2202,7 +2455,7 @@ namespace OpenSim.Region.CoreModules.World.Land
2202 } 2455 }
2203 2456
2204 report.Append(cdt.ToString()); 2457 report.Append(cdt.ToString());
2205 } 2458 }
2206 2459
2207 private void AppendParcelReport(StringBuilder report, ILandObject lo) 2460 private void AppendParcelReport(StringBuilder report, ILandObject lo)
2208 { 2461 {
@@ -2214,8 +2467,6 @@ namespace OpenSim.Region.CoreModules.World.Land
2214 cdl.AddRow("Description", ld.Description); 2467 cdl.AddRow("Description", ld.Description);
2215 cdl.AddRow("Snapshot ID", ld.SnapshotID); 2468 cdl.AddRow("Snapshot ID", ld.SnapshotID);
2216 cdl.AddRow("Area", ld.Area); 2469 cdl.AddRow("Area", ld.Area);
2217 cdl.AddRow("Starts", lo.StartPoint);
2218 cdl.AddRow("Ends", lo.EndPoint);
2219 cdl.AddRow("AABB Min", ld.AABBMin); 2470 cdl.AddRow("AABB Min", ld.AABBMin);
2220 cdl.AddRow("AABB Max", ld.AABBMax); 2471 cdl.AddRow("AABB Max", ld.AABBMax);
2221 string ownerName; 2472 string ownerName;
@@ -2233,7 +2484,7 @@ namespace OpenSim.Region.CoreModules.World.Land
2233 cdl.AddRow("GroupID", ld.GroupID); 2484 cdl.AddRow("GroupID", ld.GroupID);
2234 2485
2235 cdl.AddRow("Status", ld.Status); 2486 cdl.AddRow("Status", ld.Status);
2236 cdl.AddRow("Flags", (ParcelFlags)ld.Flags); 2487 cdl.AddRow("Flags", (ParcelFlags)ld.Flags);
2237 2488
2238 cdl.AddRow("Landing Type", (LandingType)ld.LandingType); 2489 cdl.AddRow("Landing Type", (LandingType)ld.LandingType);
2239 cdl.AddRow("User Location", ld.UserLocation); 2490 cdl.AddRow("User Location", ld.UserLocation);
@@ -2242,12 +2493,14 @@ namespace OpenSim.Region.CoreModules.World.Land
2242 cdl.AddRow("Other clean time", ld.OtherCleanTime); 2493 cdl.AddRow("Other clean time", ld.OtherCleanTime);
2243 2494
2244 cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount()); 2495 cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount());
2496 cdl.AddRow("Simwide Max Prims (owner)", lo.GetSimulatorMaxPrimCount());
2245 IPrimCounts pc = lo.PrimCounts; 2497 IPrimCounts pc = lo.PrimCounts;
2246 cdl.AddRow("Owner Prims", pc.Owner); 2498 cdl.AddRow("Owner Prims", pc.Owner);
2247 cdl.AddRow("Group Prims", pc.Group); 2499 cdl.AddRow("Group Prims", pc.Group);
2248 cdl.AddRow("Other Prims", pc.Others); 2500 cdl.AddRow("Other Prims", pc.Others);
2249 cdl.AddRow("Selected Prims", pc.Selected); 2501 cdl.AddRow("Selected Prims", pc.Selected);
2250 cdl.AddRow("Total Prims", pc.Total); 2502 cdl.AddRow("Total Prims", pc.Total);
2503 cdl.AddRow("SimWide Prims (owner)", pc.Simulator);
2251 2504
2252 cdl.AddRow("Music URL", ld.MusicURL); 2505 cdl.AddRow("Music URL", ld.MusicURL);
2253 cdl.AddRow("Obscure Music", ld.ObscureMusic); 2506 cdl.AddRow("Obscure Music", ld.ObscureMusic);
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index a0c1b9d..ce67fcc 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -50,15 +50,22 @@ 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>();
57 58
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
61 IDwellModule m_dwellModule;
60 62
61 public bool[,] LandBitmap { get; set; } 63 private bool[,] m_landBitmap;
64 public bool[,] LandBitmap
65 {
66 get { return m_landBitmap; }
67 set { m_landBitmap = value; }
68 }
62 69
63 #endregion 70 #endregion
64 71
@@ -69,7 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Land
69 return free; 76 return free;
70 } 77 }
71 78
72 public LandData LandData { get; set; } 79 protected LandData m_landData;
80 public LandData LandData
81 {
82 get { return m_landData; }
83
84 set { m_landData = value; }
85 }
73 86
74 public IPrimCounts PrimCounts { get; set; } 87 public IPrimCounts PrimCounts { get; set; }
75 88
@@ -78,77 +91,230 @@ namespace OpenSim.Region.CoreModules.World.Land
78 get { return m_scene.RegionInfo.RegionID; } 91 get { return m_scene.RegionInfo.RegionID; }
79 } 92 }
80 93
81 public Vector3 StartPoint 94 private Vector2 m_startPoint = Vector2.Zero;
95 private Vector2 m_endPoint = Vector2.Zero;
96 private Vector2 m_centerPoint = Vector2.Zero;
97 private Vector2 m_AABBmin = Vector2.Zero;
98 private Vector2 m_AABBmax = Vector2.Zero;
99
100 public Vector2 StartPoint
82 { 101 {
83 get 102 get
84 { 103 {
85 for (int y = 0; y < LandBitmap.GetLength(1); y++) 104 return m_startPoint;
86 { 105 }
87 for (int x = 0; x < LandBitmap.GetLength(0); x++) 106 }
88 {
89 if (LandBitmap[x, y])
90 return new Vector3(x * landUnit, y * landUnit, 0);
91 }
92 }
93 107
94 m_log.ErrorFormat("{0} StartPoint. No start point found. bitmapSize=<{1},{2}>", 108 public Vector2 EndPoint
95 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 109 {
96 return new Vector3(-1, -1, -1); 110 get
111 {
112 return m_endPoint;
97 } 113 }
98 } 114 }
99 115
100 public Vector3 EndPoint 116 //estimate a center point of a parcel
117 public Vector2 CenterPoint
101 { 118 {
102 get 119 get
103 { 120 {
104 for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--) 121 return m_centerPoint;
122 }
123 }
124
125 public Vector2? GetNearestPoint(Vector3 pos)
126 {
127 Vector3 direction = new Vector3(m_centerPoint.X - pos.X, m_centerPoint.Y - pos.Y, 0f );
128 return GetNearestPointAlongDirection(pos, direction);
129 }
130
131 public Vector2? GetNearestPointAlongDirection(Vector3 pos, Vector3 pdirection)
132 {
133 Vector2 testpos;
134 Vector2 direction;
135
136 testpos.X = pos.X / landUnit;
137 testpos.Y = pos.Y / landUnit;
138
139 if(LandBitmap[(int)testpos.X, (int)testpos.Y])
140 return new Vector2(pos.X, pos.Y); // we are already here
141
142 direction.X = pdirection.X;
143 direction.Y = pdirection.Y;
144
145 if(direction.X == 0f && direction.Y == 0f)
146 return null; // we can't look anywhere
147
148 direction.Normalize();
149
150 int minx = (int)(m_AABBmin.X / landUnit);
151 int maxx = (int)(m_AABBmax.X / landUnit);
152
153 // check against AABB
154 if(direction.X > 0f)
155 {
156 if(testpos.X >= maxx)
157 return null; // will never get there
158 if(testpos.X < minx)
159 testpos.X = minx;
160 }
161 else if(direction.X < 0f)
162 {
163 if(testpos.X < minx)
164 return null; // will never get there
165 if(testpos.X >= maxx)
166 testpos.X = maxx - 1;
167 }
168 else
169 {
170 if(testpos.X < minx)
171 return null; // will never get there
172 else if(testpos.X >= maxx)
173 return null; // will never get there
174 }
175
176 int miny = (int)(m_AABBmin.Y / landUnit);
177 int maxy = (int)(m_AABBmax.Y / landUnit);
178
179 if(direction.Y > 0f)
180 {
181 if(testpos.Y >= maxy)
182 return null; // will never get there
183 if(testpos.Y < miny)
184 testpos.Y = miny;
185 }
186 else if(direction.Y < 0f)
187 {
188 if(testpos.Y < miny)
189 return null; // will never get there
190 if(testpos.Y >= maxy)
191 testpos.Y = maxy - 1;
192 }
193 else
194 {
195 if(testpos.Y < miny)
196 return null; // will never get there
197 else if(testpos.Y >= maxy)
198 return null; // will never get there
199 }
200
201 while(!LandBitmap[(int)testpos.X, (int)testpos.Y])
202 {
203 testpos += direction;
204
205 if(testpos.X < minx)
206 return null;
207 if (testpos.X >= maxx)
208 return null;
209 if(testpos.Y < miny)
210 return null;
211 if (testpos.Y >= maxy)
212 return null;
213 }
214
215 testpos *= landUnit;
216 float ftmp;
217
218 if(Math.Abs(direction.X) > Math.Abs(direction.Y))
219 {
220 if(direction.X < 0)
221 testpos.X += landUnit - 0.5f;
222 else
223 testpos.X += 0.5f;
224 ftmp = testpos.X - pos.X;
225 ftmp /= direction.X;
226 ftmp = Math.Abs(ftmp);
227 ftmp *= direction.Y;
228 ftmp += pos.Y;
229
230 if(ftmp < testpos.Y + .5f)
231 ftmp = testpos.Y + .5f;
232 else
105 { 233 {
106 for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--) 234 testpos.Y += landUnit - 0.5f;
107 { 235 if(ftmp > testpos.Y)
108 if (LandBitmap[x, y]) 236 ftmp = testpos.Y;
109 {
110 return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
111 }
112 }
113 } 237 }
114 238 testpos.Y = ftmp;
115 m_log.ErrorFormat("{0} EndPoint. No end point found. bitmapSize=<{1},{2}>", 239 }
116 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 240 else
117 return new Vector3(-1, -1, -1); 241 {
242 if(direction.Y < 0)
243 testpos.Y += landUnit - 0.5f;
244 else
245 testpos.Y += 0.5f;
246 ftmp = testpos.Y - pos.Y;
247 ftmp /= direction.Y;
248 ftmp = Math.Abs(ftmp);
249 ftmp *= direction.X;
250 ftmp += pos.X;
251
252 if(ftmp < testpos.X + .5f)
253 ftmp = testpos.X + .5f;
254 else
255 {
256 testpos.X += landUnit - 0.5f;
257 if(ftmp > testpos.X)
258 ftmp = testpos.X;
259 }
260 testpos.X = ftmp;
118 } 261 }
262 return testpos;
119 } 263 }
120 264
265
121 #region Constructors 266 #region Constructors
122 267
123 public LandObject(LandData landData, Scene scene) 268 public LandObject(LandData landData, Scene scene)
124 { 269 {
125 LandData = landData.Copy(); 270 LandData = landData.Copy();
126 m_scene = scene; 271 m_scene = scene;
272 m_scene.EventManager.OnFrame += OnFrame;
273 m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
127 } 274 }
128 275
129 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 276 public LandObject(UUID owner_id, bool is_group_owned, Scene scene, LandData data = null)
130 { 277 {
131 m_scene = scene; 278 m_scene = scene;
132 if (m_scene == null) 279 if (m_scene == null)
133 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit]; 280 LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit];
134 else 281 else
282 {
135 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 283 LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
284 m_dwellModule = m_scene.RequestModuleInterface<IDwellModule>();
285 }
286
287 if(data == null)
288 LandData = new LandData();
289 else
290 LandData = data;
136 291
137 LandData = new LandData();
138 LandData.OwnerID = owner_id; 292 LandData.OwnerID = owner_id;
139 if (is_group_owned) 293 if (is_group_owned)
140 LandData.GroupID = owner_id; 294 LandData.GroupID = owner_id;
141 else 295
142 LandData.GroupID = UUID.Zero;
143 LandData.IsGroupOwned = is_group_owned; 296 LandData.IsGroupOwned = is_group_owned;
297
298 if(m_dwellModule == null)
299 LandData.Dwell = 0;
300
301 m_scene.EventManager.OnFrame += OnFrame;
302 }
303
304 public void Clear()
305 {
306 if(m_scene != null)
307 m_scene.EventManager.OnFrame -= OnFrame;
308 LandData = null;
144 } 309 }
145 310
311
146 #endregion 312 #endregion
147 313
148 #region Member Functions 314 #region Member Functions
149 315
150 #region General Functions 316 #region General Functions
151 317
152 /// <summary> 318 /// <summary>
153 /// Checks to see if this land object contains a point 319 /// Checks to see if this land object contains a point
154 /// </summary> 320 /// </summary>
@@ -195,14 +361,22 @@ namespace OpenSim.Region.CoreModules.World.Land
195 else 361 else
196 { 362 {
197 // Normal Calculations 363 // Normal Calculations
198 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 364 int parcelMax = (int)(
199 * (float)m_scene.RegionInfo.ObjectCapacity 365 (double)LandData.Area
200 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 366 * (double)m_scene.RegionInfo.ObjectCapacity
201 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 367 * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
368 / (double)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
369 + 0.5 );
370
371 if(parcelMax > m_scene.RegionInfo.ObjectCapacity)
372 parcelMax = m_scene.RegionInfo.ObjectCapacity;
373
374 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
202 return parcelMax; 375 return parcelMax;
203 } 376 }
204 } 377 }
205 378
379 // the total prims a parcel owner can have on a region
206 public int GetSimulatorMaxPrimCount() 380 public int GetSimulatorMaxPrimCount()
207 { 381 {
208 if (overrideSimulatorMaxPrimCount != null) 382 if (overrideSimulatorMaxPrimCount != null)
@@ -212,18 +386,34 @@ namespace OpenSim.Region.CoreModules.World.Land
212 else 386 else
213 { 387 {
214 //Normal Calculations 388 //Normal Calculations
215 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 389 int simMax = (int)( (double)LandData.SimwideArea
216 * (float)m_scene.RegionInfo.ObjectCapacity); 390 * (double)m_scene.RegionInfo.ObjectCapacity
391 * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus
392 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)
393 +0.5 );
394 // sanity check
395 if(simMax > m_scene.RegionInfo.ObjectCapacity)
396 simMax = m_scene.RegionInfo.ObjectCapacity;
397 //m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}, SimWidePrims {3}",
398 // LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax, LandData.SimwidePrims);
217 return simMax; 399 return simMax;
218 } 400 }
219 } 401 }
220 402
221 #endregion 403 #endregion
222 404
223 #region Packet Request Handling 405 #region Packet Request Handling
224 406
225 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 407 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
226 { 408 {
409 if(m_scene.RegionInfo.RegionSettings.AllowDamage)
410 remote_client.SceneAgent.Invulnerable = false;
411 else
412 remote_client.SceneAgent.Invulnerable = (m_landData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
413
414 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
415 return;
416
227 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 417 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
228 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 418 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
229 uint regionFlags = (uint)(RegionFlags.PublicAllowed 419 uint regionFlags = (uint)(RegionFlags.PublicAllowed
@@ -252,10 +442,11 @@ namespace OpenSim.Region.CoreModules.World.Land
252 GetSimulatorMaxPrimCount(), regionFlags); 442 GetSimulatorMaxPrimCount(), regionFlags);
253 } 443 }
254 444
255 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) 445 public bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
256 { 446 {
257 //Needs later group support 447 //Needs later group support
258 bool snap_selection = false; 448 snap_selection = false;
449 needOverlay = false;
259 LandData newData = LandData.Copy(); 450 LandData newData = LandData.Copy();
260 451
261 uint allowedDelta = 0; 452 uint allowedDelta = 0;
@@ -264,7 +455,7 @@ namespace OpenSim.Region.CoreModules.World.Land
264 // ParcelFlags.ForSaleObjects 455 // ParcelFlags.ForSaleObjects
265 // ParcelFlags.LindenHome 456 // ParcelFlags.LindenHome
266 457
267 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 458 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, false))
268 { 459 {
269 allowedDelta |= (uint)(ParcelFlags.AllowLandmark | 460 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
270 ParcelFlags.AllowTerraform | 461 ParcelFlags.AllowTerraform |
@@ -277,9 +468,12 @@ namespace OpenSim.Region.CoreModules.World.Land
277 ParcelFlags.AllowAPrimitiveEntry | 468 ParcelFlags.AllowAPrimitiveEntry |
278 ParcelFlags.AllowGroupObjectEntry | 469 ParcelFlags.AllowGroupObjectEntry |
279 ParcelFlags.AllowFly); 470 ParcelFlags.AllowFly);
471 newData.SeeAVs = args.SeeAVs;
472 newData.AnyAVSounds = args.AnyAVSounds;
473 newData.GroupAVSounds = args.GroupAVSounds;
280 } 474 }
281 475
282 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale)) 476 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true))
283 { 477 {
284 if (args.AuthBuyerID != newData.AuthBuyerID || 478 if (args.AuthBuyerID != newData.AuthBuyerID ||
285 args.SalePrice != newData.SalePrice) 479 args.SalePrice != newData.SalePrice)
@@ -302,30 +496,30 @@ namespace OpenSim.Region.CoreModules.World.Land
302 allowedDelta |= (uint)ParcelFlags.ForSale; 496 allowedDelta |= (uint)ParcelFlags.ForSale;
303 } 497 }
304 498
305 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces)) 499 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces, false))
306 { 500 {
307 newData.Category = args.Category; 501 newData.Category = args.Category;
308 502
309 allowedDelta |= (uint)(ParcelFlags.ShowDirectory | 503 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
310 ParcelFlags.AllowPublish | 504 ParcelFlags.AllowPublish |
311 ParcelFlags.MaturePublish); 505 ParcelFlags.MaturePublish) | (uint)(1 << 23);
312 } 506 }
313 507
314 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity)) 508 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity, false))
315 { 509 {
316 newData.Description = args.Desc; 510 newData.Description = args.Desc;
317 newData.Name = args.Name; 511 newData.Name = args.Name;
318 newData.SnapshotID = args.SnapshotID; 512 newData.SnapshotID = args.SnapshotID;
319 } 513 }
320 514
321 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint)) 515 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint, false))
322 { 516 {
323 newData.LandingType = args.LandingType; 517 newData.LandingType = args.LandingType;
324 newData.UserLocation = args.UserLocation; 518 newData.UserLocation = args.UserLocation;
325 newData.UserLookAt = args.UserLookAt; 519 newData.UserLookAt = args.UserLookAt;
326 } 520 }
327 521
328 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia)) 522 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia, false))
329 { 523 {
330 newData.MediaAutoScale = args.MediaAutoScale; 524 newData.MediaAutoScale = args.MediaAutoScale;
331 newData.MediaID = args.MediaID; 525 newData.MediaID = args.MediaID;
@@ -346,7 +540,8 @@ namespace OpenSim.Region.CoreModules.World.Land
346 ParcelFlags.UseEstateVoiceChan); 540 ParcelFlags.UseEstateVoiceChan);
347 } 541 }
348 542
349 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses)) 543 // don't allow passes on group owned until we can give money to groups
544 if (!newData.IsGroupOwned && m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
350 { 545 {
351 newData.PassHours = args.PassHours; 546 newData.PassHours = args.PassHours;
352 newData.PassPrice = args.PassPrice; 547 newData.PassPrice = args.PassPrice;
@@ -354,13 +549,13 @@ namespace OpenSim.Region.CoreModules.World.Land
354 allowedDelta |= (uint)ParcelFlags.UsePassList; 549 allowedDelta |= (uint)ParcelFlags.UsePassList;
355 } 550 }
356 551
357 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed)) 552 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed, false))
358 { 553 {
359 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup | 554 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
360 ParcelFlags.UseAccessList); 555 ParcelFlags.UseAccessList);
361 } 556 }
362 557
363 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned)) 558 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned, false))
364 { 559 {
365 allowedDelta |= (uint)(ParcelFlags.UseBanList | 560 allowedDelta |= (uint)(ParcelFlags.UseBanList |
366 ParcelFlags.DenyAnonymous | 561 ParcelFlags.DenyAnonymous |
@@ -372,9 +567,16 @@ namespace OpenSim.Region.CoreModules.World.Land
372 uint preserve = LandData.Flags & ~allowedDelta; 567 uint preserve = LandData.Flags & ~allowedDelta;
373 newData.Flags = preserve | (args.ParcelFlags & allowedDelta); 568 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
374 569
570 uint curdelta = LandData.Flags ^ newData.Flags;
571 curdelta &= (uint)(ParcelFlags.SoundLocal);
572
573 if(curdelta != 0 || newData.SeeAVs != LandData.SeeAVs)
574 needOverlay = true;
575
375 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 576 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
376 SendLandUpdateToAvatarsOverMe(snap_selection); 577 return true;
377 } 578 }
579 return false;
378 } 580 }
379 581
380 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 582 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -395,7 +597,7 @@ namespace OpenSim.Region.CoreModules.World.Land
395 UUID previousOwner = LandData.OwnerID; 597 UUID previousOwner = LandData.OwnerID;
396 598
397 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 599 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
398 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 600// m_scene.EventManager.TriggerParcelPrimCountUpdate();
399 SendLandUpdateToAvatarsOverMe(true); 601 SendLandUpdateToAvatarsOverMe(true);
400 602
401 if (sellObjects) SellLandObjects(previousOwner); 603 if (sellObjects) SellLandObjects(previousOwner);
@@ -431,7 +633,7 @@ namespace OpenSim.Region.CoreModules.World.Land
431 633
432 public bool CanBeOnThisLand(UUID avatar, float posHeight) 634 public bool CanBeOnThisLand(UUID avatar, float posHeight)
433 { 635 {
434 if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar)) 636 if (posHeight < LandChannel.BAN_LINE_SAFETY_HEIGHT && IsBannedFromLand(avatar))
435 { 637 {
436 return false; 638 return false;
437 } 639 }
@@ -530,7 +732,30 @@ namespace OpenSim.Region.CoreModules.World.Land
530 if (HasGroupAccess(avatar)) 732 if (HasGroupAccess(avatar))
531 return false; 733 return false;
532 734
533 return !IsInLandAccessList(avatar); 735 if(IsInLandAccessList(avatar))
736 return false;
737
738 // check for a NPC
739 ScenePresence sp;
740 if (!m_scene.TryGetScenePresence(avatar, out sp))
741 return true;
742
743 if(sp==null || !sp.IsNPC)
744 return true;
745
746 INPC npccli = (INPC)sp.ControllingClient;
747 if(npccli== null)
748 return true;
749
750 UUID owner = npccli.Owner;
751
752 if(owner == UUID.Zero)
753 return true;
754
755 if (owner == LandData.OwnerID)
756 return false;
757
758 return !IsInLandAccessList(owner);
534 } 759 }
535 760
536 public bool IsInLandAccessList(UUID avatar) 761 public bool IsInLandAccessList(UUID avatar)
@@ -568,6 +793,7 @@ namespace OpenSim.Region.CoreModules.World.Land
568 793
569 public void SendLandUpdateToAvatarsOverMe(bool snap_selection) 794 public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
570 { 795 {
796 m_scene.EventManager.TriggerParcelPrimCountUpdate();
571 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar) 797 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
572 { 798 {
573 ILandObject over = null; 799 ILandObject over = null;
@@ -587,13 +813,13 @@ namespace OpenSim.Region.CoreModules.World.Land
587 { 813 {
588 if (over.LandData.LocalID == LandData.LocalID) 814 if (over.LandData.LocalID == LandData.LocalID)
589 { 815 {
590 if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && 816 if(m_scene.RegionInfo.RegionSettings.AllowDamage)
591 m_scene.RegionInfo.RegionSettings.AllowDamage)
592 avatar.Invulnerable = false; 817 avatar.Invulnerable = false;
593 else 818 else
594 avatar.Invulnerable = true; 819 avatar.Invulnerable = (over.LandData.Flags & (uint)ParcelFlags.AllowDamage) == 0;
595 820
596 SendLandUpdateToClient(snap_selection, avatar.ControllingClient); 821 SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
822 avatar.currentParcelUUID = LandData.GlobalID;
597 } 823 }
598 } 824 }
599 }); 825 });
@@ -630,13 +856,13 @@ namespace OpenSim.Region.CoreModules.World.Land
630 IClientAPI remote_client) 856 IClientAPI remote_client)
631 { 857 {
632 858
633 if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) 859 if ((flags & (uint) AccessList.Access) != 0)
634 { 860 {
635 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access); 861 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Access);
636 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID); 862 remote_client.SendLandAccessListData(accessEntries,(uint) AccessList.Access,LandData.LocalID);
637 } 863 }
638 864
639 if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) 865 if ((flags & (uint) AccessList.Ban) != 0)
640 { 866 {
641 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban); 867 List<LandAccessEntry> accessEntries = CreateAccessListArrayByFlag(AccessList.Ban);
642 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID); 868 remote_client.SendLandAccessListData(accessEntries, (uint)AccessList.Ban, LandData.LocalID);
@@ -691,6 +917,17 @@ namespace OpenSim.Region.CoreModules.World.Land
691 newData.ParcelAccessList.Add(temp); 917 newData.ParcelAccessList.Add(temp);
692 } 918 }
693 919
920 // update use lists flags
921 // rights already checked or we wont be here
922 uint parcelflags = newData.Flags;
923
924 if((flags & (uint)AccessList.Access) != 0)
925 parcelflags |= (uint)ParcelFlags.UseAccessList;
926 if((flags & (uint)AccessList.Ban) != 0)
927 parcelflags |= (uint)ParcelFlags.UseBanList;
928
929 newData.Flags = parcelflags;
930
694 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 931 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
695 } 932 }
696 933
@@ -708,7 +945,7 @@ namespace OpenSim.Region.CoreModules.World.Land
708 /// </summary> 945 /// </summary>
709 public void ForceUpdateLandInfo() 946 public void ForceUpdateLandInfo()
710 { 947 {
711 UpdateAABBAndAreaValues(); 948 UpdateGeometryValues();
712 UpdateLandBitmapByteArray(); 949 UpdateLandBitmapByteArray();
713 } 950 }
714 951
@@ -718,52 +955,117 @@ namespace OpenSim.Region.CoreModules.World.Land
718 } 955 }
719 956
720 /// <summary> 957 /// <summary>
721 /// Updates the AABBMin and AABBMax values after area/shape modification of the land object 958 /// Updates geomtric values after area/shape modification of the land object
722 /// </summary> 959 /// </summary>
723 private void UpdateAABBAndAreaValues() 960 private void UpdateGeometryValues()
724 { 961 {
725 int min_x = 10000; 962 int min_x = Int32.MaxValue;
726 int min_y = 10000; 963 int min_y = Int32.MaxValue;
727 int max_x = 0; 964 int max_x = Int32.MinValue;
728 int max_y = 0; 965 int max_y = Int32.MinValue;
729 int tempArea = 0; 966 int tempArea = 0;
730 int x, y; 967 int x, y;
968
969 int lastX = 0;
970 int lastY = 0;
971 float avgx = 0f;
972 float avgy = 0f;
973
974 bool needFirst = true;
975
731 for (x = 0; x < LandBitmap.GetLength(0); x++) 976 for (x = 0; x < LandBitmap.GetLength(0); x++)
732 { 977 {
733 for (y = 0; y < LandBitmap.GetLength(1); y++) 978 for (y = 0; y < LandBitmap.GetLength(1); y++)
734 { 979 {
735 if (LandBitmap[x, y] == true) 980 if (LandBitmap[x, y])
736 { 981 {
737 if (min_x > x) min_x = x; 982 if (min_x > x)
738 if (min_y > y) min_y = y; 983 min_x = x;
739 if (max_x < x) max_x = x; 984 if (min_y > y)
740 if (max_y < y) max_y = y; 985 min_y = y;
741 tempArea += landUnit * landUnit; //16sqm peice of land 986 if (max_x < x)
987 max_x = x;
988 if (max_y < y)
989 max_y = y;
990
991 if(needFirst)
992 {
993 avgx = x;
994 avgy = y;
995 m_startPoint.X = x * landUnit;
996 m_startPoint.Y = y * landUnit;
997 needFirst = false;
998 }
999 else
1000 {
1001 // keeping previus odd average
1002 avgx = (avgx * tempArea + x) / (tempArea + 1);
1003 avgy = (avgy * tempArea + y) / (tempArea + 1);
1004 }
1005
1006 tempArea++;
1007
1008 lastX = x;
1009 lastY = y;
742 } 1010 }
743 } 1011 }
744 } 1012 }
1013
1014 int halfunit = landUnit/2;
1015
1016 m_centerPoint.X = avgx * landUnit + halfunit;
1017 m_centerPoint.Y = avgy * landUnit + halfunit;
1018
1019 m_endPoint.X = lastX * landUnit + landUnit;
1020 m_endPoint.Y = lastY * landUnit + landUnit;
1021
1022 // next tests should not be needed
1023 // if they fail, something is wrong
1024
1025 int regionSizeX = (int)Constants.RegionSize;
1026 int regionSizeY = (int)Constants.RegionSize;
1027
1028 if(m_scene != null)
1029 {
1030 regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
1031 regionSizeY = (int)m_scene.RegionInfo.RegionSizeX;
1032 }
1033
745 int tx = min_x * landUnit; 1034 int tx = min_x * landUnit;
746 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 1035 if (tx >= regionSizeX)
747 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 1036 tx = regionSizeX - 1;
1037
748 int ty = min_y * landUnit; 1038 int ty = min_y * landUnit;
749 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 1039 if (ty >= regionSizeY)
750 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 1040 ty = regionSizeY - 1;
751 1041
752 LandData.AABBMin = 1042 m_AABBmin.X = tx;
753 new Vector3( 1043 m_AABBmin.Y = ty;
754 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 1044
1045 if(m_scene == null || m_scene.Heightmap == null)
1046 LandData.AABBMin = new Vector3(tx, ty, 0f);
1047 else
1048 LandData.AABBMin = new Vector3(tx, ty, (float)m_scene.Heightmap[tx, ty]);
755 1049
1050 max_x++;
756 tx = max_x * landUnit; 1051 tx = max_x * landUnit;
757 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 1052 if (tx > regionSizeX)
758 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 1053 tx = regionSizeX;
1054
1055 max_y++;
759 ty = max_y * landUnit; 1056 ty = max_y * landUnit;
760 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 1057 if (ty > regionSizeY)
761 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 1058 ty = regionSizeY;
1059
1060 m_AABBmax.X = tx;
1061 m_AABBmax.Y = ty;
762 1062
763 LandData.AABBMax 1063 if(m_scene == null || m_scene.Heightmap == null)
764 = new Vector3( 1064 LandData.AABBMax = new Vector3(tx, ty, 0f);
765 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 1065 else
1066 LandData.AABBMax = new Vector3(tx, ty, (float)m_scene.Heightmap[tx - 1, ty - 1]);
766 1067
1068 tempArea *= landUnit * landUnit;
767 LandData.Area = tempArea; 1069 LandData.Area = tempArea;
768 } 1070 }
769 1071
@@ -778,7 +1080,6 @@ namespace OpenSim.Region.CoreModules.World.Land
778 public void SetLandBitmap(bool[,] bitmap) 1080 public void SetLandBitmap(bool[,] bitmap)
779 { 1081 {
780 LandBitmap = bitmap; 1082 LandBitmap = bitmap;
781 // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
782 ForceUpdateLandInfo(); 1083 ForceUpdateLandInfo();
783 } 1084 }
784 1085
@@ -793,17 +1094,17 @@ namespace OpenSim.Region.CoreModules.World.Land
793 1094
794 public bool[,] BasicFullRegionLandBitmap() 1095 public bool[,] BasicFullRegionLandBitmap()
795 { 1096 {
796 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY); 1097 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY, true);
797 } 1098 }
798 1099
799 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) 1100 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y, bool set_value = true)
800 { 1101 {
801 // Empty bitmap for the whole region 1102 // Empty bitmap for the whole region
802 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 1103 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
803 tempBitmap.Initialize(); 1104 tempBitmap.Initialize();
804 1105
805 // Fill the bitmap square area specified by state and end 1106 // Fill the bitmap square area specified by state and end
806 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); 1107 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, set_value);
807 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>", 1108 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>",
808 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1)); 1109 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1));
809 return tempBitmap; 1110 return tempBitmap;
@@ -873,51 +1174,287 @@ namespace OpenSim.Region.CoreModules.World.Land
873 } 1174 }
874 1175
875 /// <summary> 1176 /// <summary>
1177 /// Remap a land bitmap. Takes the supplied land bitmap and rotates it, crops it and finally offsets it into
1178 /// a final land bitmap of the target region size.
1179 /// </summary>
1180 /// <param name="bitmap_base">The original parcel bitmap</param>
1181 /// <param name="rotationDegrees"></param>
1182 /// <param name="displacement">&lt;x,y,?&gt;</param>
1183 /// <param name="boundingOrigin">&lt;x,y,?&gt;</param>
1184 /// <param name="boundingSize">&lt;x,y,?&gt;</param>
1185 /// <param name="regionSize">&lt;x,y,?&gt;</param>
1186 /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
1187 /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
1188 /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
1189 /// <returns>New parcel bitmap</returns>
1190 public bool[,] RemapLandBitmap(bool[,] bitmap_base, Vector2 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Vector2 regionSize, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1191 {
1192 // get the size of the incoming bitmap
1193 int baseX = bitmap_base.GetLength(0);
1194 int baseY = bitmap_base.GetLength(1);
1195
1196 // create an intermediate bitmap that is 25% bigger on each side that we can work with to handle rotations
1197 int offsetX = baseX / 4; // the original origin will now be at these coordinates so now we can have imaginary negative coordinates ;)
1198 int offsetY = baseY / 4;
1199 int tmpX = baseX + baseX / 2;
1200 int tmpY = baseY + baseY / 2;
1201 int centreX = tmpX / 2;
1202 int centreY = tmpY / 2;
1203 bool[,] bitmap_tmp = new bool[tmpX, tmpY];
1204
1205 double radianRotation = Math.PI * rotationDegrees / 180f;
1206 double cosR = Math.Cos(radianRotation);
1207 double sinR = Math.Sin(radianRotation);
1208 if (rotationDegrees < 0f) rotationDegrees += 360f; //-90=270 -180=180 -270=90
1209
1210 // So first we apply the rotation to the incoming bitmap, storing the result in bitmap_tmp
1211 // We special case orthogonal rotations for accuracy because even using double precision math, Math.Cos(90 degrees) is never fully 0
1212 // and we can never rotate around a centre pixel because the bitmap size is always even
1213 int x, y, sx, sy;
1214 for (y = 0; y <= tmpY; y++)
1215 {
1216 for (x = 0; x <= tmpX; x++)
1217 {
1218 if (rotationDegrees == 0f)
1219 {
1220 sx = x - offsetX;
1221 sy = y - offsetY;
1222 }
1223 else if (rotationDegrees == 90f)
1224 {
1225 sx = y - offsetX;
1226 sy = tmpY - 1 - x - offsetY;
1227 }
1228 else if (rotationDegrees == 180f)
1229 {
1230 sx = tmpX - 1 - x - offsetX;
1231 sy = tmpY - 1 - y - offsetY;
1232 }
1233 else if (rotationDegrees == 270f)
1234 {
1235 sx = tmpX - 1 - y - offsetX;
1236 sy = x - offsetY;
1237 }
1238 else
1239 {
1240 // arbitary rotation: hmmm should I be using (centreX - 0.5) and (centreY - 0.5) and round cosR and sinR to say only 5 decimal places?
1241 sx = centreX + (int)Math.Round((((double)x - centreX) * cosR) + (((double)y - centreY) * sinR)) - offsetX;
1242 sy = centreY + (int)Math.Round((((double)y - centreY) * cosR) - (((double)x - centreX) * sinR)) - offsetY;
1243 }
1244 if (sx >= 0 && sx < baseX && sy >= 0 && sy < baseY)
1245 {
1246 try
1247 {
1248 if (bitmap_base[sx, sy]) bitmap_tmp[x, y] = true;
1249 }
1250 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
1251 {
1252 m_log.DebugFormat("{0} RemapLandBitmap Rotate: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, sx, sy, x, y);
1253 }
1254 }
1255 }
1256 }
1257
1258 // We could also incorporate the next steps, bounding-rectangle and displacement in the loop above, but it's simpler to visualise if done separately
1259 // and will also make it much easier when later I want the option for maybe a circular or oval bounding shape too ;).
1260 // So... our output land bitmap must be the size of the current region but rememeber, parcel landbitmaps are landUnit metres (4x4 metres) per point,
1261 // and region sizes, boundaries and displacements are in metres so we need to scale down
1262
1263 int newX = (int)(regionSize.X / landUnit);
1264 int newY = (int)(regionSize.Y / landUnit);
1265 bool[,] bitmap_new = new bool[newX, newY];
1266 // displacement is relative to <0,0> in the destination region and defines where the origin of the data selected by the bounding-rectangle is placed
1267 int dispX = (int)Math.Floor(displacement.X / landUnit);
1268 int dispY = (int)Math.Floor(displacement.Y / landUnit);
1269
1270 // startX/Y and endX/Y are coordinates in bitmap_tmp
1271 int startX = (int)Math.Floor(boundingOrigin.X / landUnit) + offsetX;
1272 if (startX > tmpX) startX = tmpX;
1273 if (startX < 0) startX = 0;
1274 int startY = (int)Math.Floor(boundingOrigin.Y / landUnit) + offsetY;
1275 if (startY > tmpY) startY = tmpY;
1276 if (startY < 0) startY = 0;
1277
1278 int endX = (int)Math.Floor((boundingOrigin.X + boundingSize.X) / landUnit) + offsetX;
1279 if (endX > tmpX) endX = tmpX;
1280 if (endX < 0) endX = 0;
1281 int endY = (int)Math.Floor((boundingOrigin.Y + boundingSize.Y) / landUnit) + offsetY;
1282 if (endY > tmpY) endY = tmpY;
1283 if (endY < 0) endY = 0;
1284
1285 //m_log.DebugFormat("{0} RemapLandBitmap: inSize=<{1},{2}>, disp=<{3},{4}> rot={5}, offset=<{6},{7}>, boundingStart=<{8},{9}>, boundingEnd=<{10},{11}>, cosR={12}, sinR={13}, outSize=<{14},{15}>", LogHeader,
1286 // baseX, baseY, dispX, dispY, radianRotation, offsetX, offsetY, startX, startY, endX, endY, cosR, sinR, newX, newY);
1287
1288 isEmptyNow = true;
1289 int minX = newX;
1290 int minY = newY;
1291 int maxX = 0;
1292 int maxY = 0;
1293
1294 int dx, dy;
1295 for (y = startY; y < endY; y++)
1296 {
1297 for (x = startX; x < endX; x++)
1298 {
1299 dx = x - startX + dispX;
1300 dy = y - startY + dispY;
1301 if (dx >= 0 && dx < newX && dy >= 0 && dy < newY)
1302 {
1303 try
1304 {
1305 if (bitmap_tmp[x, y])
1306 {
1307 bitmap_new[dx, dy] = true;
1308 isEmptyNow = false;
1309 if (dx < minX) minX = dx;
1310 if (dy < minY) minY = dy;
1311 if (dx > maxX) maxX = dx;
1312 if (dy > maxY) maxY = dy;
1313 }
1314 }
1315 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
1316 {
1317 m_log.DebugFormat("{0} RemapLandBitmap - Bound & Displace: Out of Bounds sx={1} sy={2} dx={3} dy={4}", LogHeader, x, y, dx, dy);
1318 }
1319 }
1320 }
1321 }
1322 if (isEmptyNow)
1323 {
1324 //m_log.DebugFormat("{0} RemapLandBitmap: Land bitmap is marked as Empty", LogHeader);
1325 minX = 0;
1326 minY = 0;
1327 }
1328
1329 AABBMin = new Vector3(minX * landUnit, minY * landUnit, 0);
1330 AABBMax = new Vector3(maxX * landUnit, maxY * landUnit, 0);
1331 return bitmap_new;
1332 }
1333
1334 /// <summary>
1335 /// Clears any parcel data in bitmap_base where there exists parcel data in bitmap_new. In other words the parcel data
1336 /// in bitmap_new takes over the space of the parcel data in bitmap_base.
1337 /// </summary>
1338 /// <param name="bitmap_base"></param>
1339 /// <param name="bitmap_new"></param>
1340 /// <param name="isEmptyNow">out: This is set if the resultant bitmap is now empty</param>
1341 /// <param name="AABBMin">out: parcel.AABBMin &lt;x,y,0&gt</param>
1342 /// <param name="AABBMax">out: parcel.AABBMax &lt;x,y,0&gt</param>
1343 /// <returns>New parcel bitmap</returns>
1344 public bool[,] RemoveFromLandBitmap(bool[,] bitmap_base, bool[,] bitmap_new, out bool isEmptyNow, out Vector3 AABBMin, out Vector3 AABBMax)
1345 {
1346 // get the size of the incoming bitmaps
1347 int baseX = bitmap_base.GetLength(0);
1348 int baseY = bitmap_base.GetLength(1);
1349 int newX = bitmap_new.GetLength(0);
1350 int newY = bitmap_new.GetLength(1);
1351
1352 if (baseX != newX || baseY != newY)
1353 {
1354 throw new Exception(
1355 String.Format("{0} RemoveFromLandBitmap: Land bitmaps are not the same size! baseX={1} baseY={2} newX={3} newY={4}", LogHeader, baseX, baseY, newX, newY));
1356 }
1357
1358 isEmptyNow = true;
1359 int minX = baseX;
1360 int minY = baseY;
1361 int maxX = 0;
1362 int maxY = 0;
1363
1364 for (int y = 0; y < baseY; y++)
1365 {
1366 for (int x = 0; x < baseX; x++)
1367 {
1368 if (bitmap_new[x, y]) bitmap_base[x, y] = false;
1369 if (bitmap_base[x, y])
1370 {
1371 isEmptyNow = false;
1372 if (x < minX) minX = x;
1373 if (y < minY) minY = y;
1374 if (x > maxX) maxX = x;
1375 if (y > maxY) maxY = y;
1376 }
1377 }
1378 }
1379 if (isEmptyNow)
1380 {
1381 //m_log.DebugFormat("{0} RemoveFromLandBitmap: Land bitmap is marked as Empty", LogHeader);
1382 minX = 0;
1383 minY = 0;
1384 }
1385 AABBMin = new Vector3(minX * landUnit, minY * landUnit, 0);
1386 AABBMax = new Vector3(maxX * landUnit, maxY * landUnit, 0);
1387 return bitmap_base;
1388 }
1389
1390 /// <summary>
876 /// Converts the land bitmap to a packet friendly byte array 1391 /// Converts the land bitmap to a packet friendly byte array
877 /// </summary> 1392 /// </summary>
878 /// <returns></returns> 1393 /// <returns></returns>
879 private byte[] ConvertLandBitmapToBytes() 1394 public byte[] ConvertLandBitmapToBytes()
880 { 1395 {
881 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8]; 1396 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
882 byte tempByte = 0; 1397
1398 int tempByte = 0;
883 int byteNum = 0; 1399 int byteNum = 0;
884 int i = 0; 1400 int mask = 1;
885 for (int y = 0; y < LandBitmap.GetLength(1); y++) 1401 for (int y = 0; y < LandBitmap.GetLength(1); y++)
886 { 1402 {
887 for (int x = 0; x < LandBitmap.GetLength(0); x++) 1403 for (int x = 0; x < LandBitmap.GetLength(0); x++)
888 { 1404 {
889 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 1405 if (LandBitmap[x, y])
890 if (i % 8 == 0) 1406 tempByte |= mask;
1407 mask = mask << 1;
1408 if (mask == 0x100)
891 { 1409 {
892 tempConvertArr[byteNum] = tempByte; 1410 mask = 1;
893 tempByte = (byte) 0; 1411 tempConvertArr[byteNum++] = (byte)tempByte;
894 i = 0; 1412 tempByte = 0;
895 byteNum++;
896 } 1413 }
897 } 1414 }
898 } 1415 }
899 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>", 1416
900 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 1417 if(tempByte != 0 && byteNum < 512)
1418 tempConvertArr[byteNum] = (byte)tempByte;
1419
901 return tempConvertArr; 1420 return tempConvertArr;
902 } 1421 }
903 1422
904 private bool[,] ConvertBytesToLandBitmap() 1423 public bool[,] ConvertBytesToLandBitmap(bool overrideRegionSize = false)
905 { 1424 {
906 bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; 1425 int bitmapLen;
907 tempConvertMap.Initialize(); 1426 int xLen;
908 byte tempByte = 0; 1427 bool[,] tempConvertMap;
909 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
910 int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
911 int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
912 1428
913 if (bitmapLen == 512) 1429 if (overrideRegionSize)
1430 {
1431 // Importing land parcel data from an OAR where the source region is a different size to the dest region requires us
1432 // to make a LandBitmap that's not derived from the current region's size. We use the LandData.Bitmap size in bytes
1433 // to figure out what the OAR's region dimensions are. (Is there a better way to get the src region x and y from the OAR?)
1434 // This method assumes we always will have square regions
1435
1436 bitmapLen = LandData.Bitmap.Length;
1437 xLen = (int)Math.Abs(Math.Sqrt(bitmapLen * 8));
1438 tempConvertMap = new bool[xLen, xLen];
1439 tempConvertMap.Initialize();
1440 }
1441 else
914 { 1442 {
915 // Legacy bitmap being passed in. Use the legacy region size 1443 tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
916 // and only set the lower area of the larger region. 1444 tempConvertMap.Initialize();
917 xLen = (int)(Constants.RegionSize / landUnit); 1445 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
1446 bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
1447 xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
1448 if (bitmapLen == 512)
1449 {
1450 // Legacy bitmap being passed in. Use the legacy region size
1451 // and only set the lower area of the larger region.
1452 xLen = (int)(Constants.RegionSize / landUnit);
1453 }
918 } 1454 }
919 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen); 1455 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
920 1456
1457 byte tempByte;
921 int x = 0, y = 0; 1458 int x = 0, y = 0;
922 for (int i = 0; i < bitmapLen; i++) 1459 for (int i = 0; i < bitmapLen; i++)
923 { 1460 {
@@ -945,13 +1482,39 @@ namespace OpenSim.Region.CoreModules.World.Land
945 return tempConvertMap; 1482 return tempConvertMap;
946 } 1483 }
947 1484
1485 public bool IsLandBitmapEmpty(bool[,] landBitmap)
1486 {
1487 for (int y = 0; y < landBitmap.GetLength(1); y++)
1488 {
1489 for (int x = 0; x < landBitmap.GetLength(0); x++)
1490 {
1491 if (landBitmap[x, y]) return false;
1492 }
1493 }
1494 return true;
1495 }
1496
1497 public void DebugLandBitmap(bool[,] landBitmap)
1498 {
1499 m_log.InfoFormat("{0}: Map Key: #=claimed land .=unclaimed land.", LogHeader);
1500 for (int y = landBitmap.GetLength(1) - 1; y >= 0; y--)
1501 {
1502 string row = "";
1503 for (int x = 0; x < landBitmap.GetLength(0); x++)
1504 {
1505 row += landBitmap[x, y] ? "#" : ".";
1506 }
1507 m_log.InfoFormat("{0}: {1}", LogHeader, row);
1508 }
1509 }
1510
948 #endregion 1511 #endregion
949 1512
950 #region Object Select and Object Owner Listing 1513 #region Object Select and Object Owner Listing
951 1514
952 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client) 1515 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
953 { 1516 {
954 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1517 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
955 { 1518 {
956 List<uint> resultLocalIDs = new List<uint>(); 1519 List<uint> resultLocalIDs = new List<uint>();
957 try 1520 try
@@ -1001,7 +1564,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1001 /// </param> 1564 /// </param>
1002 public void SendLandObjectOwners(IClientAPI remote_client) 1565 public void SendLandObjectOwners(IClientAPI remote_client)
1003 { 1566 {
1004 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1567 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
1005 { 1568 {
1006 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>(); 1569 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
1007 List<UUID> groups = new List<UUID>(); 1570 List<UUID> groups = new List<UUID>();
@@ -1009,9 +1572,9 @@ namespace OpenSim.Region.CoreModules.World.Land
1009 lock (primsOverMe) 1572 lock (primsOverMe)
1010 { 1573 {
1011// m_log.DebugFormat( 1574// m_log.DebugFormat(
1012// "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region", 1575// "[LAND OBJECT]: Request for SendLandObjectOwners() from {0} with {1} known prims on region",
1013// remote_client.Name, primsOverMe.Count); 1576// remote_client.Name, primsOverMe.Count);
1014 1577
1015 try 1578 try
1016 { 1579 {
1017 foreach (SceneObjectGroup obj in primsOverMe) 1580 foreach (SceneObjectGroup obj in primsOverMe)
@@ -1052,7 +1615,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1052 public Dictionary<UUID, int> GetLandObjectOwners() 1615 public Dictionary<UUID, int> GetLandObjectOwners()
1053 { 1616 {
1054 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>(); 1617 Dictionary<UUID, int> ownersAndCount = new Dictionary<UUID, int>();
1055 1618
1056 lock (primsOverMe) 1619 lock (primsOverMe)
1057 { 1620 {
1058 try 1621 try
@@ -1106,8 +1669,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1106 { 1669 {
1107 foreach (SceneObjectGroup obj in primsOverMe) 1670 foreach (SceneObjectGroup obj in primsOverMe)
1108 { 1671 {
1109 if (obj.OwnerID == previousOwner && obj.GroupID == UUID.Zero && 1672 if(m_scene.Permissions.CanSellObject(previousOwner,obj, (byte)SaleType.Original))
1110 (obj.GetEffectivePermissions() & (uint)(OpenSim.Framework.PermissionMask.Transfer)) != 0)
1111 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0); 1673 m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0);
1112 } 1674 }
1113 } 1675 }
@@ -1121,14 +1683,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1121 { 1683 {
1122 SceneObjectGroup[] objs = new SceneObjectGroup[1]; 1684 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1123 objs[0] = obj; 1685 objs[0] = obj;
1124 m_scene.returnObjects(objs, obj.OwnerID); 1686 m_scene.returnObjects(objs, null);
1125 } 1687 }
1126 1688
1127 public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) 1689 public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client)
1128 { 1690 {
1129// m_log.DebugFormat( 1691// m_log.DebugFormat(
1130// "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name); 1692// "[LAND OBJECT]: Request to return objects in {0} from {1}", LandData.Name, remote_client.Name);
1131 1693
1132 Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>(); 1694 Dictionary<UUID,List<SceneObjectGroup>> returns = new Dictionary<UUID,List<SceneObjectGroup>>();
1133 1695
1134 lock (primsOverMe) 1696 lock (primsOverMe)
@@ -1152,6 +1714,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1152 { 1714 {
1153 if (obj.GroupID == LandData.GroupID) 1715 if (obj.GroupID == LandData.GroupID)
1154 { 1716 {
1717 if (obj.OwnerID == LandData.OwnerID)
1718 continue;
1155 if (!returns.ContainsKey(obj.OwnerID)) 1719 if (!returns.ContainsKey(obj.OwnerID))
1156 returns[obj.OwnerID] = 1720 returns[obj.OwnerID] =
1157 new List<SceneObjectGroup>(); 1721 new List<SceneObjectGroup>();
@@ -1193,8 +1757,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1193 1757
1194 foreach (List<SceneObjectGroup> ol in returns.Values) 1758 foreach (List<SceneObjectGroup> ol in returns.Values)
1195 { 1759 {
1196 if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) 1760 if (m_scene.Permissions.CanReturnObjects(this, remote_client, ol))
1197 m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); 1761 m_scene.returnObjects(ol.ToArray(), remote_client);
1198 } 1762 }
1199 } 1763 }
1200 1764
@@ -1211,7 +1775,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1211 public void AddPrimOverMe(SceneObjectGroup obj) 1775 public void AddPrimOverMe(SceneObjectGroup obj)
1212 { 1776 {
1213// m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name); 1777// m_log.DebugFormat("[LAND OBJECT]: Adding scene object {0} {1} over {2}", obj.Name, obj.LocalId, LandData.Name);
1214 1778
1215 lock (primsOverMe) 1779 lock (primsOverMe)
1216 primsOverMe.Add(obj); 1780 primsOverMe.Add(obj);
1217 } 1781 }
@@ -1219,13 +1783,13 @@ namespace OpenSim.Region.CoreModules.World.Land
1219 public void RemovePrimFromOverMe(SceneObjectGroup obj) 1783 public void RemovePrimFromOverMe(SceneObjectGroup obj)
1220 { 1784 {
1221// m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name); 1785// m_log.DebugFormat("[LAND OBJECT]: Removing scene object {0} {1} from over {2}", obj.Name, obj.LocalId, LandData.Name);
1222 1786
1223 lock (primsOverMe) 1787 lock (primsOverMe)
1224 primsOverMe.Remove(obj); 1788 primsOverMe.Remove(obj);
1225 } 1789 }
1226 1790
1227 #endregion 1791 #endregion
1228 1792
1229 /// <summary> 1793 /// <summary>
1230 /// Set the media url for this land parcel 1794 /// Set the media url for this land parcel
1231 /// </summary> 1795 /// </summary>
@@ -1233,9 +1797,10 @@ namespace OpenSim.Region.CoreModules.World.Land
1233 public void SetMediaUrl(string url) 1797 public void SetMediaUrl(string url)
1234 { 1798 {
1235 LandData.MediaURL = url; 1799 LandData.MediaURL = url;
1800 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1236 SendLandUpdateToAvatarsOverMe(); 1801 SendLandUpdateToAvatarsOverMe();
1237 } 1802 }
1238 1803
1239 /// <summary> 1804 /// <summary>
1240 /// Set the music url for this land parcel 1805 /// Set the music url for this land parcel
1241 /// </summary> 1806 /// </summary>
@@ -1243,6 +1808,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1243 public void SetMusicUrl(string url) 1808 public void SetMusicUrl(string url)
1244 { 1809 {
1245 LandData.MusicURL = url; 1810 LandData.MusicURL = url;
1811 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1246 SendLandUpdateToAvatarsOverMe(); 1812 SendLandUpdateToAvatarsOverMe();
1247 } 1813 }
1248 1814
@@ -1257,6 +1823,48 @@ namespace OpenSim.Region.CoreModules.World.Land
1257 1823
1258 #endregion 1824 #endregion
1259 1825
1826 private void OnFrame()
1827 {
1828 m_expiryCounter++;
1829
1830 if (m_expiryCounter >= 50)
1831 {
1832 ExpireAccessList();
1833 m_expiryCounter = 0;
1834 }
1835
1836 // need to update dwell here bc landdata has no parent info
1837 if(LandData != null && m_dwellModule != null)
1838 {
1839 double now = Util.GetTimeStampMS();
1840 double elapsed = now - LandData.LastDwellTimeMS;
1841 if(elapsed > 150000) //2.5 minutes resolution / throttle
1842 {
1843 float dwell = LandData.Dwell;
1844 double cur = dwell * 60000.0;
1845 double decay = 1.5e-8 * cur * elapsed;
1846 cur -= decay;
1847 if(cur < 0)
1848 cur = 0;
1849
1850 UUID lgid = LandData.GlobalID;
1851 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
1852 {
1853 if(sp.IsNPC || sp.IsLoggingIn || sp.IsDeleted || sp.currentParcelUUID != lgid)
1854 return;
1855 cur += (now - sp.ParcelDwellTickMS);
1856 sp.ParcelDwellTickMS = now;
1857 });
1858
1859 float newdwell = (float)(cur * 1.666666666667e-5);
1860 LandData.Dwell = newdwell;
1861
1862 if(Math.Abs(newdwell - dwell) >= 0.9)
1863 m_scene.EventManager.TriggerLandObjectAdded(this);
1864 }
1865 }
1866 }
1867
1260 private void ExpireAccessList() 1868 private void ExpireAccessList()
1261 { 1869 {
1262 List<LandAccessEntry> delete = new List<LandAccessEntry>(); 1870 List<LandAccessEntry> delete = new List<LandAccessEntry>();
@@ -1267,7 +1875,22 @@ namespace OpenSim.Region.CoreModules.World.Land
1267 delete.Add(entry); 1875 delete.Add(entry);
1268 } 1876 }
1269 foreach (LandAccessEntry entry in delete) 1877 foreach (LandAccessEntry entry in delete)
1878 {
1270 LandData.ParcelAccessList.Remove(entry); 1879 LandData.ParcelAccessList.Remove(entry);
1880 ScenePresence presence;
1881
1882 if (m_scene.TryGetScenePresence(entry.AgentID, out presence) && (!presence.IsChildAgent))
1883 {
1884 ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
1885 if (land.LandData.LocalID == LandData.LocalID)
1886 {
1887 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1888 presence.TeleportOnEject(pos);
1889 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
1890 }
1891 }
1892 m_log.DebugFormat("[LAND]: Removing entry {0} because it has expired", entry.AgentID);
1893 }
1271 1894
1272 if (delete.Count > 0) 1895 if (delete.Count > 0)
1273 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this); 1896 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..2a720db 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -69,11 +69,11 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// For now, a simple simwide taint to get this up. Later parcel based 69 /// For now, a simple simwide taint to get this up. Later parcel based
70 /// taint to allow recounting a parcel if only ownership has changed 70 /// taint to allow recounting a parcel if only ownership has changed
71 /// without recounting the whole sim. 71 /// without recounting the whole sim.
72 /// 72 ///
73 /// We start out tainted so that the first get call resets the various prim counts. 73 /// We start out tainted so that the first get call resets the various prim counts.
74 /// </value> 74 /// </value>
75 private bool m_Tainted = true; 75 private bool m_Tainted = true;
76 76
77 private Object m_TaintLock = new Object(); 77 private Object m_TaintLock = new Object();
78 78
79 public Type ReplaceableInterface 79 public Type ReplaceableInterface
@@ -88,14 +88,12 @@ namespace OpenSim.Region.CoreModules.World.Land
88 public void AddRegion(Scene scene) 88 public void AddRegion(Scene scene)
89 { 89 {
90 m_Scene = scene; 90 m_Scene = scene;
91 91
92 m_Scene.RegisterModuleInterface<IPrimCountModule>(this); 92 m_Scene.RegisterModuleInterface<IPrimCountModule>(this);
93 93
94 m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd; 94 m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd;
95 m_Scene.EventManager.OnObjectBeingRemovedFromScene += 95 m_Scene.EventManager.OnObjectBeingRemovedFromScene += OnObjectBeingRemovedFromScene;
96 OnObjectBeingRemovedFromScene; 96 m_Scene.EventManager.OnParcelPrimCountTainted += OnParcelPrimCountTainted;
97 m_Scene.EventManager.OnParcelPrimCountTainted +=
98 OnParcelPrimCountTainted;
99 m_Scene.EventManager.OnLandObjectAdded += delegate(ILandObject lo) { OnParcelPrimCountTainted(); }; 97 m_Scene.EventManager.OnLandObjectAdded += delegate(ILandObject lo) { OnParcelPrimCountTainted(); };
100 } 98 }
101 99
@@ -104,7 +102,7 @@ namespace OpenSim.Region.CoreModules.World.Land
104 } 102 }
105 103
106 public void RemoveRegion(Scene scene) 104 public void RemoveRegion(Scene scene)
107 { 105 {
108 } 106 }
109 107
110 public void Close() 108 public void Close()
@@ -126,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Land
126 AddObject(obj); 124 AddObject(obj);
127// else 125// else
128// m_log.DebugFormat( 126// m_log.DebugFormat(
129// "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted", 127// "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted",
130// obj.Name, m_Scene.RegionInfo.RegionName); 128// obj.Name, m_Scene.RegionInfo.RegionName);
131 } 129 }
132 } 130 }
@@ -140,16 +138,16 @@ namespace OpenSim.Region.CoreModules.World.Land
140 RemoveObject(obj); 138 RemoveObject(obj);
141// else 139// else
142// m_log.DebugFormat( 140// m_log.DebugFormat(
143// "[PRIM COUNT MODULE]: Ignoring OnObjectBeingRemovedFromScene() for {0} on {1} since count is tainted", 141// "[PRIM COUNT MODULE]: Ignoring OnObjectBeingRemovedFromScene() for {0} on {1} since count is tainted",
144// obj.Name, m_Scene.RegionInfo.RegionName); 142// obj.Name, m_Scene.RegionInfo.RegionName);
145 } 143 }
146 } 144 }
147 145
148 private void OnParcelPrimCountTainted() 146 private void OnParcelPrimCountTainted()
149 { 147 {
150// m_log.DebugFormat( 148// m_log.DebugFormat(
151// "[PRIM COUNT MODULE]: OnParcelPrimCountTainted() called on {0}", m_Scene.RegionInfo.RegionName); 149// "[PRIM COUNT MODULE]: OnParcelPrimCountTainted() called on {0}", m_Scene.RegionInfo.RegionName);
152 150
153 lock (m_TaintLock) 151 lock (m_TaintLock)
154 m_Tainted = true; 152 m_Tainted = true;
155 } 153 }
@@ -174,40 +172,40 @@ namespace OpenSim.Region.CoreModules.World.Land
174 172
175 // NOTE: Call under Taint Lock 173 // NOTE: Call under Taint Lock
176 private void AddObject(SceneObjectGroup obj) 174 private void AddObject(SceneObjectGroup obj)
177 { 175 {
178 if (obj.IsAttachment) 176 if (obj.IsAttachment)
179 return; 177 return;
180 if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) 178 if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0))
181 return; 179 return;
182 180
183 Vector3 pos = obj.AbsolutePosition; 181 Vector3 pos = obj.AbsolutePosition;
184 ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); 182 ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
185 183
186 // If for some reason there is no land object (perhaps the object is out of bounds) then we can't count it 184 // If for some reason there is no land object (perhaps the object is out of bounds) then we can't count it
187 if (landObject == null) 185 if (landObject == null)
188 { 186 {
189// m_log.WarnFormat( 187// m_log.WarnFormat(
190// "[PRIM COUNT MODULE]: Found no land object for {0} at position ({1}, {2}) on {3}", 188// "[PRIM COUNT MODULE]: Found no land object for {0} at position ({1}, {2}) on {3}",
191// obj.Name, pos.X, pos.Y, m_Scene.RegionInfo.RegionName); 189// obj.Name, pos.X, pos.Y, m_Scene.RegionInfo.RegionName);
192 190
193 return; 191 return;
194 } 192 }
195 193
196 LandData landData = landObject.LandData; 194 LandData landData = landObject.LandData;
197 195
198// m_log.DebugFormat( 196// m_log.DebugFormat(
199// "[PRIM COUNT MODULE]: Adding object {0} with {1} parts to prim count for parcel {2} on {3}", 197// "[PRIM COUNT MODULE]: Adding object {0} with {1} parts to prim count for parcel {2} on {3}",
200// obj.Name, obj.Parts.Length, landData.Name, m_Scene.RegionInfo.RegionName); 198// obj.Name, obj.Parts.Length, landData.Name, m_Scene.RegionInfo.RegionName);
201 199
202// m_log.DebugFormat( 200// m_log.DebugFormat(
203// "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}", 201// "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}",
204// obj.Name, obj.OwnerID, landData.OwnerID); 202// obj.Name, obj.OwnerID, landData.OwnerID);
205 203
206 ParcelCounts parcelCounts; 204 ParcelCounts parcelCounts;
207 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) 205 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
208 { 206 {
209 UUID landOwner = landData.OwnerID; 207 UUID landOwner = landData.OwnerID;
210 int partCount = obj.Parts.Length; 208 int partCount = obj.GetPartCount();
211 209
212 m_SimwideCounts[landOwner] += partCount; 210 m_SimwideCounts[landOwner] += partCount;
213 if (parcelCounts.Users.ContainsKey(obj.OwnerID)) 211 if (parcelCounts.Users.ContainsKey(obj.OwnerID))
@@ -215,37 +213,23 @@ namespace OpenSim.Region.CoreModules.World.Land
215 else 213 else
216 parcelCounts.Users[obj.OwnerID] = partCount; 214 parcelCounts.Users[obj.OwnerID] = partCount;
217 215
218 if (obj.IsSelected) 216 if (obj.IsSelected || obj.GetSittingAvatarsCount() > 0)
219 { 217 parcelCounts.Selected += partCount;
220 parcelCounts.Selected += partCount; 218
221 } 219 if (obj.OwnerID == landData.OwnerID)
220 parcelCounts.Owner += partCount;
221 else if (landData.GroupID != UUID.Zero && obj.GroupID == landData.GroupID)
222 parcelCounts.Group += partCount;
222 else 223 else
223 { 224 parcelCounts.Others += partCount;
224 if (landData.IsGroupOwned)
225 {
226 if (obj.OwnerID == landData.GroupID)
227 parcelCounts.Owner += partCount;
228 else if (landData.GroupID != UUID.Zero && obj.GroupID == landData.GroupID)
229 parcelCounts.Group += partCount;
230 else
231 parcelCounts.Others += partCount;
232 }
233 else
234 {
235 if (obj.OwnerID == landData.OwnerID)
236 parcelCounts.Owner += partCount;
237 else
238 parcelCounts.Others += partCount;
239 }
240 }
241 } 225 }
242 } 226 }
243 227
244 // NOTE: Call under Taint Lock 228 // NOTE: Call under Taint Lock
245 private void RemoveObject(SceneObjectGroup obj) 229 private void RemoveObject(SceneObjectGroup obj)
246 { 230 {
247// m_log.DebugFormat("[PRIM COUNT MODULE]: Removing object {0} {1} from prim count", obj.Name, obj.UUID); 231// m_log.DebugFormat("[PRIM COUNT MODULE]: Removing object {0} {1} from prim count", obj.Name, obj.UUID);
248 232
249 // Currently this is being done by tainting the count instead. 233 // Currently this is being done by tainting the count instead.
250 } 234 }
251 235
@@ -253,7 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Land
253 { 237 {
254// m_log.DebugFormat( 238// m_log.DebugFormat(
255// "[PRIM COUNT MODULE]: GetPrimCounts for parcel {0} in {1}", parcelID, m_Scene.RegionInfo.RegionName); 239// "[PRIM COUNT MODULE]: GetPrimCounts for parcel {0} in {1}", parcelID, m_Scene.RegionInfo.RegionName);
256 240
257 PrimCounts primCounts; 241 PrimCounts primCounts;
258 242
259 lock (m_PrimCounts) 243 lock (m_PrimCounts)
@@ -267,7 +251,7 @@ namespace OpenSim.Region.CoreModules.World.Land
267 return primCounts; 251 return primCounts;
268 } 252 }
269 253
270 254
271 /// <summary> 255 /// <summary>
272 /// Get the number of prims on the parcel that are owned by the parcel owner. 256 /// Get the number of prims on the parcel that are owned by the parcel owner.
273 /// </summary> 257 /// </summary>
@@ -276,7 +260,7 @@ namespace OpenSim.Region.CoreModules.World.Land
276 public int GetOwnerCount(UUID parcelID) 260 public int GetOwnerCount(UUID parcelID)
277 { 261 {
278 int count = 0; 262 int count = 0;
279 263
280 lock (m_TaintLock) 264 lock (m_TaintLock)
281 { 265 {
282 if (m_Tainted) 266 if (m_Tainted)
@@ -286,11 +270,11 @@ namespace OpenSim.Region.CoreModules.World.Land
286 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 270 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
287 count = counts.Owner; 271 count = counts.Owner;
288 } 272 }
289 273
290// m_log.DebugFormat( 274// m_log.DebugFormat(
291// "[PRIM COUNT MODULE]: GetOwnerCount for parcel {0} in {1} returning {2}", 275// "[PRIM COUNT MODULE]: GetOwnerCount for parcel {0} in {1} returning {2}",
292// parcelID, m_Scene.RegionInfo.RegionName, count); 276// parcelID, m_Scene.RegionInfo.RegionName, count);
293 277
294 return count; 278 return count;
295 } 279 }
296 280
@@ -298,11 +282,11 @@ namespace OpenSim.Region.CoreModules.World.Land
298 /// Get the number of prims on the parcel that have been set to the group that owns the parcel. 282 /// Get the number of prims on the parcel that have been set to the group that owns the parcel.
299 /// </summary> 283 /// </summary>
300 /// <param name="parcelID"></param> 284 /// <param name="parcelID"></param>
301 /// <returns></returns> 285 /// <returns></returns>
302 public int GetGroupCount(UUID parcelID) 286 public int GetGroupCount(UUID parcelID)
303 { 287 {
304 int count = 0; 288 int count = 0;
305 289
306 lock (m_TaintLock) 290 lock (m_TaintLock)
307 { 291 {
308 if (m_Tainted) 292 if (m_Tainted)
@@ -312,11 +296,11 @@ namespace OpenSim.Region.CoreModules.World.Land
312 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 296 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
313 count = counts.Group; 297 count = counts.Group;
314 } 298 }
315 299
316// m_log.DebugFormat( 300// m_log.DebugFormat(
317// "[PRIM COUNT MODULE]: GetGroupCount for parcel {0} in {1} returning {2}", 301// "[PRIM COUNT MODULE]: GetGroupCount for parcel {0} in {1} returning {2}",
318// parcelID, m_Scene.RegionInfo.RegionName, count); 302// parcelID, m_Scene.RegionInfo.RegionName, count);
319 303
320 return count; 304 return count;
321 } 305 }
322 306
@@ -324,11 +308,11 @@ namespace OpenSim.Region.CoreModules.World.Land
324 /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group. 308 /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group.
325 /// </summary> 309 /// </summary>
326 /// <param name="parcelID"></param> 310 /// <param name="parcelID"></param>
327 /// <returns></returns> 311 /// <returns></returns>
328 public int GetOthersCount(UUID parcelID) 312 public int GetOthersCount(UUID parcelID)
329 { 313 {
330 int count = 0; 314 int count = 0;
331 315
332 lock (m_TaintLock) 316 lock (m_TaintLock)
333 { 317 {
334 if (m_Tainted) 318 if (m_Tainted)
@@ -338,23 +322,23 @@ namespace OpenSim.Region.CoreModules.World.Land
338 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 322 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
339 count = counts.Others; 323 count = counts.Others;
340 } 324 }
341 325
342// m_log.DebugFormat( 326// m_log.DebugFormat(
343// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}", 327// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
344// parcelID, m_Scene.RegionInfo.RegionName, count); 328// parcelID, m_Scene.RegionInfo.RegionName, count);
345 329
346 return count; 330 return count;
347 } 331 }
348 332
349 /// <summary> 333 /// <summary>
350 /// Get the number of selected prims. 334 /// Get the number of selected prims.
351 /// </summary> 335 /// </summary>
352 /// <param name="parcelID"></param> 336 /// <param name="parcelID"></param>
353 /// <returns></returns> 337 /// <returns></returns>
354 public int GetSelectedCount(UUID parcelID) 338 public int GetSelectedCount(UUID parcelID)
355 { 339 {
356 int count = 0; 340 int count = 0;
357 341
358 lock (m_TaintLock) 342 lock (m_TaintLock)
359 { 343 {
360 if (m_Tainted) 344 if (m_Tainted)
@@ -364,24 +348,24 @@ namespace OpenSim.Region.CoreModules.World.Land
364 if (m_ParcelCounts.TryGetValue(parcelID, out counts)) 348 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
365 count = counts.Selected; 349 count = counts.Selected;
366 } 350 }
367 351
368// m_log.DebugFormat( 352// m_log.DebugFormat(
369// "[PRIM COUNT MODULE]: GetSelectedCount for parcel {0} in {1} returning {2}", 353// "[PRIM COUNT MODULE]: GetSelectedCount for parcel {0} in {1} returning {2}",
370// parcelID, m_Scene.RegionInfo.RegionName, count); 354// parcelID, m_Scene.RegionInfo.RegionName, count);
371 355
372 return count; 356 return count;
373 } 357 }
374 358
375 /// <summary> 359 /// <summary>
376 /// Get the total count of owner, group and others prims on the parcel. 360 /// Get the total count of owner, group and others prims on the parcel.
377 /// FIXME: Need to do selected prims once this is reimplemented. 361 /// FIXME: Need to do selected prims once this is reimplemented.
378 /// </summary> 362 /// </summary>
379 /// <param name="parcelID"></param> 363 /// <param name="parcelID"></param>
380 /// <returns></returns> 364 /// <returns></returns>
381 public int GetTotalCount(UUID parcelID) 365 public int GetTotalCount(UUID parcelID)
382 { 366 {
383 int count = 0; 367 int count = 0;
384 368
385 lock (m_TaintLock) 369 lock (m_TaintLock)
386 { 370 {
387 if (m_Tainted) 371 if (m_Tainted)
@@ -393,31 +377,30 @@ namespace OpenSim.Region.CoreModules.World.Land
393 count = counts.Owner; 377 count = counts.Owner;
394 count += counts.Group; 378 count += counts.Group;
395 count += counts.Others; 379 count += counts.Others;
396 count += counts.Selected;
397 } 380 }
398 } 381 }
399 382
400// m_log.DebugFormat( 383// m_log.DebugFormat(
401// "[PRIM COUNT MODULE]: GetTotalCount for parcel {0} in {1} returning {2}", 384// "[PRIM COUNT MODULE]: GetTotalCount for parcel {0} in {1} returning {2}",
402// parcelID, m_Scene.RegionInfo.RegionName, count); 385// parcelID, m_Scene.RegionInfo.RegionName, count);
403 386
404 return count; 387 return count;
405 } 388 }
406 389
407 /// <summary> 390 /// <summary>
408 /// Get the number of prims that are in the entire simulator for the owner of this parcel. 391 /// Get the number of prims that are in the entire simulator for the owner of this parcel.
409 /// </summary> 392 /// </summary>
410 /// <param name="parcelID"></param> 393 /// <param name="parcelID"></param>
411 /// <returns></returns> 394 /// <returns></returns>
412 public int GetSimulatorCount(UUID parcelID) 395 public int GetSimulatorCount(UUID parcelID)
413 { 396 {
414 int count = 0; 397 int count = 0;
415 398
416 lock (m_TaintLock) 399 lock (m_TaintLock)
417 { 400 {
418 if (m_Tainted) 401 if (m_Tainted)
419 Recount(); 402 Recount();
420 403
421 UUID owner; 404 UUID owner;
422 if (m_OwnerMap.TryGetValue(parcelID, out owner)) 405 if (m_OwnerMap.TryGetValue(parcelID, out owner))
423 { 406 {
@@ -426,11 +409,11 @@ namespace OpenSim.Region.CoreModules.World.Land
426 count = val; 409 count = val;
427 } 410 }
428 } 411 }
429 412
430// m_log.DebugFormat( 413// m_log.DebugFormat(
431// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}", 414// "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
432// parcelID, m_Scene.RegionInfo.RegionName, count); 415// parcelID, m_Scene.RegionInfo.RegionName, count);
433 416
434 return count; 417 return count;
435 } 418 }
436 419
@@ -439,11 +422,11 @@ namespace OpenSim.Region.CoreModules.World.Land
439 /// </summary> 422 /// </summary>
440 /// <param name="parcelID"></param> 423 /// <param name="parcelID"></param>
441 /// <param name="userID"></param> 424 /// <param name="userID"></param>
442 /// <returns></returns> 425 /// <returns></returns>
443 public int GetUserCount(UUID parcelID, UUID userID) 426 public int GetUserCount(UUID parcelID, UUID userID)
444 { 427 {
445 int count = 0; 428 int count = 0;
446 429
447 lock (m_TaintLock) 430 lock (m_TaintLock)
448 { 431 {
449 if (m_Tainted) 432 if (m_Tainted)
@@ -459,9 +442,9 @@ namespace OpenSim.Region.CoreModules.World.Land
459 } 442 }
460 443
461// m_log.DebugFormat( 444// m_log.DebugFormat(
462// "[PRIM COUNT MODULE]: GetUserCount for user {0} in parcel {1} in region {2} returning {3}", 445// "[PRIM COUNT MODULE]: GetUserCount for user {0} in parcel {1} in region {2} returning {3}",
463// userID, parcelID, m_Scene.RegionInfo.RegionName, count); 446// userID, parcelID, m_Scene.RegionInfo.RegionName, count);
464 447
465 return count; 448 return count;
466 } 449 }
467 450
@@ -469,13 +452,13 @@ namespace OpenSim.Region.CoreModules.World.Land
469 private void Recount() 452 private void Recount()
470 { 453 {
471// m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName); 454// m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName);
472 455
473 m_OwnerMap.Clear(); 456 m_OwnerMap.Clear();
474 m_SimwideCounts.Clear(); 457 m_SimwideCounts.Clear();
475 m_ParcelCounts.Clear(); 458 m_ParcelCounts.Clear();
476 459
477 List<ILandObject> land = m_Scene.LandChannel.AllParcels(); 460 List<ILandObject> land = m_Scene.LandChannel.AllParcels();
478 461
479 foreach (ILandObject l in land) 462 foreach (ILandObject l in land)
480 { 463 {
481 LandData landData = l.LandData; 464 LandData landData = l.LandData;
@@ -483,7 +466,7 @@ namespace OpenSim.Region.CoreModules.World.Land
483 m_OwnerMap[landData.GlobalID] = landData.OwnerID; 466 m_OwnerMap[landData.GlobalID] = landData.OwnerID;
484 m_SimwideCounts[landData.OwnerID] = 0; 467 m_SimwideCounts[landData.OwnerID] = 0;
485// m_log.DebugFormat( 468// m_log.DebugFormat(
486// "[PRIM COUNT MODULE]: Initializing parcel count for {0} on {1}", 469// "[PRIM COUNT MODULE]: Initializing parcel count for {0} on {1}",
487// landData.Name, m_Scene.RegionInfo.RegionName); 470// landData.Name, m_Scene.RegionInfo.RegionName);
488 m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); 471 m_ParcelCounts[landData.GlobalID] = new ParcelCounts();
489 } 472 }
@@ -499,7 +482,7 @@ namespace OpenSim.Region.CoreModules.World.Land
499 m_PrimCounts.Remove(k); 482 m_PrimCounts.Remove(k);
500 } 483 }
501 } 484 }
502 485
503 m_Tainted = false; 486 m_Tainted = false;
504 } 487 }
505 } 488 }
@@ -541,7 +524,7 @@ namespace OpenSim.Region.CoreModules.World.Land
541 return m_Parent.GetOthersCount(m_ParcelID); 524 return m_Parent.GetOthersCount(m_ParcelID);
542 } 525 }
543 } 526 }
544 527
545 public int Selected 528 public int Selected
546 { 529 {
547 get 530 get
@@ -549,7 +532,7 @@ namespace OpenSim.Region.CoreModules.World.Land
549 return m_Parent.GetSelectedCount(m_ParcelID); 532 return m_Parent.GetSelectedCount(m_ParcelID);
550 } 533 }
551 } 534 }
552 535
553 public int Total 536 public int Total
554 { 537 {
555 get 538 get
@@ -597,4 +580,4 @@ namespace OpenSim.Region.CoreModules.World.Land
597 } 580 }
598 } 581 }
599 } 582 }
600} \ No newline at end of file 583}
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
index 4ed67f3..d6a3ded 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs
@@ -45,14 +45,14 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
45 UUID userId = TestHelpers.ParseTail(0x1); 45 UUID userId = TestHelpers.ParseTail(0x1);
46 46
47 LandManagementModule lmm = new LandManagementModule(); 47 LandManagementModule lmm = new LandManagementModule();
48 Scene scene = new SceneHelpers().SetupScene(); 48 Scene scene = new SceneHelpers().SetupScene();
49 SceneHelpers.SetupSceneModules(scene, lmm); 49 SceneHelpers.SetupSceneModules(scene, lmm);
50 50
51 ILandObject lo = new LandObject(userId, false, scene); 51 ILandObject lo = new LandObject(userId, false, scene);
52 lo.LandData.Name = "lo1"; 52 lo.LandData.Name = "lo1";
53 lo.SetLandBitmap( 53 lo.SetLandBitmap(
54 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 54 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
55 lo = lmm.AddLandObject(lo); 55 lo = lmm.AddLandObject(lo);
56 56
57 // TODO: Should add asserts to check that land object was added properly. 57 // TODO: Should add asserts to check that land object was added properly.
58 58
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
67 { 67 {
68 ILandObject loAtCoord = lmm.GetLandObject(0, 0); 68 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
69 Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID)); 69 Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID));
70 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID)); 70 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID));
71 } 71 }
72 72
73 { 73 {
@@ -88,8 +88,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
88 88
89 SceneHelpers sh = new SceneHelpers(); 89 SceneHelpers sh = new SceneHelpers();
90 LandManagementModule lmm = new LandManagementModule(); 90 LandManagementModule lmm = new LandManagementModule();
91 Scene scene = sh.SetupScene(); 91 Scene scene = sh.SetupScene();
92 SceneHelpers.SetupSceneModules(scene, lmm); 92 SceneHelpers.SetupSceneModules(scene, lmm);
93 93
94 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID); 94 scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID);
95 95
@@ -115,8 +115,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
115 115
116 SceneHelpers sh = new SceneHelpers(); 116 SceneHelpers sh = new SceneHelpers();
117 LandManagementModule lmm = new LandManagementModule(); 117 LandManagementModule lmm = new LandManagementModule();
118 Scene scene = sh.SetupScene(); 118 Scene scene = sh.SetupScene();
119 SceneHelpers.SetupSceneModules(scene, lmm); 119 SceneHelpers.SetupSceneModules(scene, lmm);
120 120
121 ILandObject originalLo1 = new LandObject(userId, false, scene); 121 ILandObject originalLo1 = new LandObject(userId, false, scene);
122 originalLo1.LandData.Name = "lo1"; 122 originalLo1.LandData.Name = "lo1";
@@ -149,8 +149,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
149 149
150 SceneHelpers sh = new SceneHelpers(); 150 SceneHelpers sh = new SceneHelpers();
151 LandManagementModule lmm = new LandManagementModule(); 151 LandManagementModule lmm = new LandManagementModule();
152 Scene scene = sh.SetupScene(); 152 Scene scene = sh.SetupScene();
153 SceneHelpers.SetupSceneModules(scene, lmm); 153 SceneHelpers.SetupSceneModules(scene, lmm);
154 154
155 ILandObject originalLo1 = new LandObject(userId, false, scene); 155 ILandObject originalLo1 = new LandObject(userId, false, scene);
156 originalLo1.LandData.Name = "lo1"; 156 originalLo1.LandData.Name = "lo1";
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
173 Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name)); 173 Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name));
174 Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID)); 174 Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID));
175 175
176 ILandObject loAtCoord2 176 ILandObject loAtCoord2
177 = lmm.GetLandObject((int)Constants.RegionSize - 1, (((int)Constants.RegionSize / 4) * 3) - 1); 177 = lmm.GetLandObject((int)Constants.RegionSize - 1, (((int)Constants.RegionSize / 4) * 3) - 1);
178 Assert.That(loAtCoord2.LandData.Name, Is.EqualTo(originalLo2.LandData.Name)); 178 Assert.That(loAtCoord2.LandData.Name, Is.EqualTo(originalLo2.LandData.Name));
179 Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID)); 179 Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID));
@@ -198,8 +198,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
198 198
199 SceneHelpers sh = new SceneHelpers(); 199 SceneHelpers sh = new SceneHelpers();
200 LandManagementModule lmm = new LandManagementModule(); 200 LandManagementModule lmm = new LandManagementModule();
201 Scene scene = sh.SetupScene(); 201 Scene scene = sh.SetupScene();
202 SceneHelpers.SetupSceneModules(scene, lmm); 202 SceneHelpers.SetupSceneModules(scene, lmm);
203 203
204 ILandObject originalLo1 = new LandObject(userId, false, scene); 204 ILandObject originalLo1 = new LandObject(userId, false, scene);
205 originalLo1.LandData.Name = "lo1"; 205 originalLo1.LandData.Name = "lo1";
@@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
220 { 220 {
221 ILandObject loAtCoord = lmm.GetLandObject(0, 0); 221 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
222 Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo1.LandData.Name)); 222 Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo1.LandData.Name));
223 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID)); 223 Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID));
224 } 224 }
225 225
226 { 226 {
@@ -239,21 +239,21 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
239 UUID userId = TestHelpers.ParseTail(0x1); 239 UUID userId = TestHelpers.ParseTail(0x1);
240 240
241 LandManagementModule lmm = new LandManagementModule(); 241 LandManagementModule lmm = new LandManagementModule();
242 Scene scene = new SceneHelpers().SetupScene(); 242 Scene scene = new SceneHelpers().SetupScene();
243 SceneHelpers.SetupSceneModules(scene, lmm); 243 SceneHelpers.SetupSceneModules(scene, lmm);
244 244
245 ILandObject lo = new LandObject(userId, false, scene); 245 ILandObject lo = new LandObject(userId, false, scene);
246 lo.LandData.Name = "lo1"; 246 lo.LandData.Name = "lo1";
247 lo.SetLandBitmap( 247 lo.SetLandBitmap(
248 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 248 lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
249 lo = lmm.AddLandObject(lo); 249 lo = lmm.AddLandObject(lo);
250 250
251 lmm.Subdivide(0, 0, LandManagementModule.LandUnit, LandManagementModule.LandUnit, userId); 251 lmm.Subdivide(0, 0, LandManagementModule.LandUnit, LandManagementModule.LandUnit, userId);
252 252
253 { 253 {
254 ILandObject loAtCoord = lmm.GetLandObject(0, 0); 254 ILandObject loAtCoord = lmm.GetLandObject(0, 0);
255 Assert.That(loAtCoord.LandData.LocalID, Is.Not.EqualTo(lo.LandData.LocalID)); 255 Assert.That(loAtCoord.LandData.LocalID, Is.Not.EqualTo(lo.LandData.LocalID));
256 Assert.That(loAtCoord.LandData.GlobalID, Is.Not.EqualTo(lo.LandData.GlobalID)); 256 Assert.That(loAtCoord.LandData.GlobalID, Is.Not.EqualTo(lo.LandData.GlobalID));
257 } 257 }
258 258
259 { 259 {
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index 949acb6..a349aa1 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -43,21 +43,21 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
43 public class PrimCountModuleTests : OpenSimTestCase 43 public class PrimCountModuleTests : OpenSimTestCase
44 { 44 {
45 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); 45 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000");
46 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); 46 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000");
47 protected UUID m_otherUserId = new UUID("99999999-9999-9999-9999-999999999999"); 47 protected UUID m_otherUserId = new UUID("99999999-9999-9999-9999-999999999999");
48 protected TestScene m_scene; 48 protected TestScene m_scene;
49 protected PrimCountModule m_pcm; 49 protected PrimCountModule m_pcm;
50 50
51 /// <summary> 51 /// <summary>
52 /// A parcel that covers the entire sim except for a 1 unit wide strip on the eastern side. 52 /// A parcel that covers the entire sim except for a 1 unit wide strip on the eastern side.
53 /// </summary> 53 /// </summary>
54 protected ILandObject m_lo; 54 protected ILandObject m_lo;
55 55
56 /// <summary> 56 /// <summary>
57 /// A parcel that covers just the eastern strip of the sim. 57 /// A parcel that covers just the eastern strip of the sim.
58 /// </summary> 58 /// </summary>
59 protected ILandObject m_lo2; 59 protected ILandObject m_lo2;
60 60
61 [SetUp] 61 [SetUp]
62 public override void SetUp() 62 public override void SetUp()
63 { 63 {
@@ -65,24 +65,24 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
65 65
66 m_pcm = new PrimCountModule(); 66 m_pcm = new PrimCountModule();
67 LandManagementModule lmm = new LandManagementModule(); 67 LandManagementModule lmm = new LandManagementModule();
68 m_scene = new SceneHelpers().SetupScene(); 68 m_scene = new SceneHelpers().SetupScene();
69 SceneHelpers.SetupSceneModules(m_scene, lmm, m_pcm); 69 SceneHelpers.SetupSceneModules(m_scene, lmm, m_pcm);
70 70
71 int xParcelDivider = (int)Constants.RegionSize - 1; 71 int xParcelDivider = (int)Constants.RegionSize - 1;
72 72
73 ILandObject lo = new LandObject(m_userId, false, m_scene); 73 ILandObject lo = new LandObject(m_userId, false, m_scene);
74 lo.LandData.Name = "m_lo"; 74 lo.LandData.Name = "m_lo";
75 lo.SetLandBitmap( 75 lo.SetLandBitmap(
76 lo.GetSquareLandBitmap(0, 0, xParcelDivider, (int)Constants.RegionSize)); 76 lo.GetSquareLandBitmap(0, 0, xParcelDivider, (int)Constants.RegionSize));
77 m_lo = lmm.AddLandObject(lo); 77 m_lo = lmm.AddLandObject(lo);
78 78
79 ILandObject lo2 = new LandObject(m_userId, false, m_scene); 79 ILandObject lo2 = new LandObject(m_userId, false, m_scene);
80 lo2.SetLandBitmap( 80 lo2.SetLandBitmap(
81 lo2.GetSquareLandBitmap(xParcelDivider, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 81 lo2.GetSquareLandBitmap(xParcelDivider, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
82 lo2.LandData.Name = "m_lo2"; 82 lo2.LandData.Name = "m_lo2";
83 m_lo2 = lmm.AddLandObject(lo2); 83 m_lo2 = lmm.AddLandObject(lo2);
84 } 84 }
85 85
86 /// <summary> 86 /// <summary>
87 /// Test that counts before we do anything are correct. 87 /// Test that counts before we do anything are correct.
88 /// </summary> 88 /// </summary>
@@ -90,7 +90,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
90 public void TestInitialCounts() 90 public void TestInitialCounts()
91 { 91 {
92 IPrimCounts pc = m_lo.PrimCounts; 92 IPrimCounts pc = m_lo.PrimCounts;
93 93
94 Assert.That(pc.Owner, Is.EqualTo(0)); 94 Assert.That(pc.Owner, Is.EqualTo(0));
95 Assert.That(pc.Group, Is.EqualTo(0)); 95 Assert.That(pc.Group, Is.EqualTo(0));
96 Assert.That(pc.Others, Is.EqualTo(0)); 96 Assert.That(pc.Others, Is.EqualTo(0));
@@ -98,9 +98,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
98 Assert.That(pc.Selected, Is.EqualTo(0)); 98 Assert.That(pc.Selected, Is.EqualTo(0));
99 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 99 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
100 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 100 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
101 Assert.That(pc.Simulator, Is.EqualTo(0)); 101 Assert.That(pc.Simulator, Is.EqualTo(0));
102 } 102 }
103 103
104 /// <summary> 104 /// <summary>
105 /// Test count after a parcel owner owned object is added. 105 /// Test count after a parcel owner owned object is added.
106 /// </summary> 106 /// </summary>
@@ -108,13 +108,13 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
108 public void TestAddOwnerObject() 108 public void TestAddOwnerObject()
109 { 109 {
110 TestHelpers.InMethod(); 110 TestHelpers.InMethod();
111// log4net.Config.XmlConfigurator.Configure(); 111// log4net.Config.XmlConfigurator.Configure();
112 112
113 IPrimCounts pc = m_lo.PrimCounts; 113 IPrimCounts pc = m_lo.PrimCounts;
114 114
115 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 115 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
116 m_scene.AddNewSceneObject(sog, false); 116 m_scene.AddNewSceneObject(sog, false);
117 117
118 Assert.That(pc.Owner, Is.EqualTo(3)); 118 Assert.That(pc.Owner, Is.EqualTo(3));
119 Assert.That(pc.Group, Is.EqualTo(0)); 119 Assert.That(pc.Group, Is.EqualTo(0));
120 Assert.That(pc.Others, Is.EqualTo(0)); 120 Assert.That(pc.Others, Is.EqualTo(0));
@@ -122,12 +122,12 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
122 Assert.That(pc.Selected, Is.EqualTo(0)); 122 Assert.That(pc.Selected, Is.EqualTo(0));
123 Assert.That(pc.Users[m_userId], Is.EqualTo(3)); 123 Assert.That(pc.Users[m_userId], Is.EqualTo(3));
124 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 124 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
125 Assert.That(pc.Simulator, Is.EqualTo(3)); 125 Assert.That(pc.Simulator, Is.EqualTo(3));
126 126
127 // Add a second object and retest 127 // Add a second object and retest
128 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10); 128 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10);
129 m_scene.AddNewSceneObject(sog2, false); 129 m_scene.AddNewSceneObject(sog2, false);
130 130
131 Assert.That(pc.Owner, Is.EqualTo(5)); 131 Assert.That(pc.Owner, Is.EqualTo(5));
132 Assert.That(pc.Group, Is.EqualTo(0)); 132 Assert.That(pc.Group, Is.EqualTo(0));
133 Assert.That(pc.Others, Is.EqualTo(0)); 133 Assert.That(pc.Others, Is.EqualTo(0));
@@ -135,9 +135,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
135 Assert.That(pc.Selected, Is.EqualTo(0)); 135 Assert.That(pc.Selected, Is.EqualTo(0));
136 Assert.That(pc.Users[m_userId], Is.EqualTo(5)); 136 Assert.That(pc.Users[m_userId], Is.EqualTo(5));
137 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 137 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
138 Assert.That(pc.Simulator, Is.EqualTo(5)); 138 Assert.That(pc.Simulator, Is.EqualTo(5));
139 } 139 }
140 140
141 /// <summary> 141 /// <summary>
142 /// Test count after a parcel owner owned copied object is added. 142 /// Test count after a parcel owner owned copied object is added.
143 /// </summary> 143 /// </summary>
@@ -145,14 +145,14 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
145 public void TestCopyOwnerObject() 145 public void TestCopyOwnerObject()
146 { 146 {
147 TestHelpers.InMethod(); 147 TestHelpers.InMethod();
148// log4net.Config.XmlConfigurator.Configure(); 148// log4net.Config.XmlConfigurator.Configure();
149 149
150 IPrimCounts pc = m_lo.PrimCounts; 150 IPrimCounts pc = m_lo.PrimCounts;
151 151
152 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 152 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
153 m_scene.AddNewSceneObject(sog, false); 153 m_scene.AddNewSceneObject(sog, false);
154 m_scene.SceneGraph.DuplicateObject(sog.LocalId, Vector3.Zero, 0, m_userId, UUID.Zero, Quaternion.Identity); 154 m_scene.SceneGraph.DuplicateObject(sog.LocalId, Vector3.Zero, m_userId, UUID.Zero, Quaternion.Identity, false);
155 155
156 Assert.That(pc.Owner, Is.EqualTo(6)); 156 Assert.That(pc.Owner, Is.EqualTo(6));
157 Assert.That(pc.Group, Is.EqualTo(0)); 157 Assert.That(pc.Group, Is.EqualTo(0));
158 Assert.That(pc.Others, Is.EqualTo(0)); 158 Assert.That(pc.Others, Is.EqualTo(0));
@@ -160,9 +160,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
160 Assert.That(pc.Selected, Is.EqualTo(0)); 160 Assert.That(pc.Selected, Is.EqualTo(0));
161 Assert.That(pc.Users[m_userId], Is.EqualTo(6)); 161 Assert.That(pc.Users[m_userId], Is.EqualTo(6));
162 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 162 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
163 Assert.That(pc.Simulator, Is.EqualTo(6)); 163 Assert.That(pc.Simulator, Is.EqualTo(6));
164 } 164 }
165 165
166 /// <summary> 166 /// <summary>
167 /// Test that parcel counts update correctly when an object is moved between parcels, where that movement 167 /// Test that parcel counts update correctly when an object is moved between parcels, where that movement
168 /// is not done directly by the user/ 168 /// is not done directly by the user/
@@ -171,18 +171,18 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
171 public void TestMoveOwnerObject() 171 public void TestMoveOwnerObject()
172 { 172 {
173 TestHelpers.InMethod(); 173 TestHelpers.InMethod();
174// log4net.Config.XmlConfigurator.Configure(); 174// log4net.Config.XmlConfigurator.Configure();
175 175
176 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 176 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
177 m_scene.AddNewSceneObject(sog, false); 177 m_scene.AddNewSceneObject(sog, false);
178 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10); 178 SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10);
179 m_scene.AddNewSceneObject(sog2, false); 179 m_scene.AddNewSceneObject(sog2, false);
180 180
181 // Move the first scene object to the eastern strip parcel 181 // Move the first scene object to the eastern strip parcel
182 sog.AbsolutePosition = new Vector3(254, 2, 2); 182 sog.AbsolutePosition = new Vector3(254, 2, 2);
183 183
184 IPrimCounts pclo1 = m_lo.PrimCounts; 184 IPrimCounts pclo1 = m_lo.PrimCounts;
185 185
186 Assert.That(pclo1.Owner, Is.EqualTo(2)); 186 Assert.That(pclo1.Owner, Is.EqualTo(2));
187 Assert.That(pclo1.Group, Is.EqualTo(0)); 187 Assert.That(pclo1.Group, Is.EqualTo(0));
188 Assert.That(pclo1.Others, Is.EqualTo(0)); 188 Assert.That(pclo1.Others, Is.EqualTo(0));
@@ -190,10 +190,10 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
190 Assert.That(pclo1.Selected, Is.EqualTo(0)); 190 Assert.That(pclo1.Selected, Is.EqualTo(0));
191 Assert.That(pclo1.Users[m_userId], Is.EqualTo(2)); 191 Assert.That(pclo1.Users[m_userId], Is.EqualTo(2));
192 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0)); 192 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0));
193 Assert.That(pclo1.Simulator, Is.EqualTo(5)); 193 Assert.That(pclo1.Simulator, Is.EqualTo(5));
194 194
195 IPrimCounts pclo2 = m_lo2.PrimCounts; 195 IPrimCounts pclo2 = m_lo2.PrimCounts;
196 196
197 Assert.That(pclo2.Owner, Is.EqualTo(3)); 197 Assert.That(pclo2.Owner, Is.EqualTo(3));
198 Assert.That(pclo2.Group, Is.EqualTo(0)); 198 Assert.That(pclo2.Group, Is.EqualTo(0));
199 Assert.That(pclo2.Others, Is.EqualTo(0)); 199 Assert.That(pclo2.Others, Is.EqualTo(0));
@@ -201,11 +201,11 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
201 Assert.That(pclo2.Selected, Is.EqualTo(0)); 201 Assert.That(pclo2.Selected, Is.EqualTo(0));
202 Assert.That(pclo2.Users[m_userId], Is.EqualTo(3)); 202 Assert.That(pclo2.Users[m_userId], Is.EqualTo(3));
203 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0)); 203 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0));
204 Assert.That(pclo2.Simulator, Is.EqualTo(5)); 204 Assert.That(pclo2.Simulator, Is.EqualTo(5));
205 205
206 // Now move it back again 206 // Now move it back again
207 sog.AbsolutePosition = new Vector3(2, 2, 2); 207 sog.AbsolutePosition = new Vector3(2, 2, 2);
208 208
209 Assert.That(pclo1.Owner, Is.EqualTo(5)); 209 Assert.That(pclo1.Owner, Is.EqualTo(5));
210 Assert.That(pclo1.Group, Is.EqualTo(0)); 210 Assert.That(pclo1.Group, Is.EqualTo(0));
211 Assert.That(pclo1.Others, Is.EqualTo(0)); 211 Assert.That(pclo1.Others, Is.EqualTo(0));
@@ -213,8 +213,8 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
213 Assert.That(pclo1.Selected, Is.EqualTo(0)); 213 Assert.That(pclo1.Selected, Is.EqualTo(0));
214 Assert.That(pclo1.Users[m_userId], Is.EqualTo(5)); 214 Assert.That(pclo1.Users[m_userId], Is.EqualTo(5));
215 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0)); 215 Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0));
216 Assert.That(pclo1.Simulator, Is.EqualTo(5)); 216 Assert.That(pclo1.Simulator, Is.EqualTo(5));
217 217
218 Assert.That(pclo2.Owner, Is.EqualTo(0)); 218 Assert.That(pclo2.Owner, Is.EqualTo(0));
219 Assert.That(pclo2.Group, Is.EqualTo(0)); 219 Assert.That(pclo2.Group, Is.EqualTo(0));
220 Assert.That(pclo2.Others, Is.EqualTo(0)); 220 Assert.That(pclo2.Others, Is.EqualTo(0));
@@ -222,9 +222,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
222 Assert.That(pclo2.Selected, Is.EqualTo(0)); 222 Assert.That(pclo2.Selected, Is.EqualTo(0));
223 Assert.That(pclo2.Users[m_userId], Is.EqualTo(0)); 223 Assert.That(pclo2.Users[m_userId], Is.EqualTo(0));
224 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0)); 224 Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0));
225 Assert.That(pclo2.Simulator, Is.EqualTo(5)); 225 Assert.That(pclo2.Simulator, Is.EqualTo(5));
226 } 226 }
227 227
228 /// <summary> 228 /// <summary>
229 /// Test count after a parcel owner owned object is removed. 229 /// Test count after a parcel owner owned object is removed.
230 /// </summary> 230 /// </summary>
@@ -233,14 +233,14 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
233 { 233 {
234 TestHelpers.InMethod(); 234 TestHelpers.InMethod();
235// log4net.Config.XmlConfigurator.Configure(); 235// log4net.Config.XmlConfigurator.Configure();
236 236
237 IPrimCounts pc = m_lo.PrimCounts; 237 IPrimCounts pc = m_lo.PrimCounts;
238 238
239 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1), false); 239 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1), false);
240 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10); 240 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10);
241 m_scene.AddNewSceneObject(sogToDelete, false); 241 m_scene.AddNewSceneObject(sogToDelete, false);
242 m_scene.DeleteSceneObject(sogToDelete, false); 242 m_scene.DeleteSceneObject(sogToDelete, false);
243 243
244 Assert.That(pc.Owner, Is.EqualTo(1)); 244 Assert.That(pc.Owner, Is.EqualTo(1));
245 Assert.That(pc.Group, Is.EqualTo(0)); 245 Assert.That(pc.Group, Is.EqualTo(0));
246 Assert.That(pc.Others, Is.EqualTo(0)); 246 Assert.That(pc.Others, Is.EqualTo(0));
@@ -248,37 +248,37 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
248 Assert.That(pc.Selected, Is.EqualTo(0)); 248 Assert.That(pc.Selected, Is.EqualTo(0));
249 Assert.That(pc.Users[m_userId], Is.EqualTo(1)); 249 Assert.That(pc.Users[m_userId], Is.EqualTo(1));
250 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 250 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
251 Assert.That(pc.Simulator, Is.EqualTo(1)); 251 Assert.That(pc.Simulator, Is.EqualTo(1));
252 } 252 }
253 253
254 [Test] 254 [Test]
255 public void TestAddGroupObject() 255 public void TestAddGroupObject()
256 { 256 {
257 TestHelpers.InMethod(); 257 TestHelpers.InMethod();
258// log4net.Config.XmlConfigurator.Configure(); 258// log4net.Config.XmlConfigurator.Configure();
259 259
260 m_lo.DeedToGroup(m_groupId); 260 m_lo.DeedToGroup(m_groupId);
261 261
262 IPrimCounts pc = m_lo.PrimCounts; 262 IPrimCounts pc = m_lo.PrimCounts;
263 263
264 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01); 264 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01);
265 sog.GroupID = m_groupId; 265 sog.GroupID = m_groupId;
266 m_scene.AddNewSceneObject(sog, false); 266 m_scene.AddNewSceneObject(sog, false);
267 267
268 Assert.That(pc.Owner, Is.EqualTo(0)); 268 Assert.That(pc.Owner, Is.EqualTo(0));
269 Assert.That(pc.Group, Is.EqualTo(3)); 269 Assert.That(pc.Group, Is.EqualTo(3));
270 Assert.That(pc.Others, Is.EqualTo(0)); 270 Assert.That(pc.Others, Is.EqualTo(0));
271 Assert.That(pc.Total, Is.EqualTo(3)); 271 Assert.That(pc.Total, Is.EqualTo(3));
272 Assert.That(pc.Selected, Is.EqualTo(0)); 272 Assert.That(pc.Selected, Is.EqualTo(0));
273 273
274 // Is this desired behaviour? Not totally sure. 274 // Is this desired behaviour? Not totally sure.
275 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 275 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
276 Assert.That(pc.Users[m_groupId], Is.EqualTo(0)); 276 Assert.That(pc.Users[m_groupId], Is.EqualTo(0));
277 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3)); 277 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3));
278 278
279 Assert.That(pc.Simulator, Is.EqualTo(3)); 279 Assert.That(pc.Simulator, Is.EqualTo(3));
280 } 280 }
281 281
282 /// <summary> 282 /// <summary>
283 /// Test count after a parcel owner owned object is removed. 283 /// Test count after a parcel owner owned object is removed.
284 /// </summary> 284 /// </summary>
@@ -287,19 +287,19 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
287 { 287 {
288 TestHelpers.InMethod(); 288 TestHelpers.InMethod();
289// log4net.Config.XmlConfigurator.Configure(); 289// log4net.Config.XmlConfigurator.Configure();
290 290
291 m_lo.DeedToGroup(m_groupId); 291 m_lo.DeedToGroup(m_groupId);
292 292
293 IPrimCounts pc = m_lo.PrimCounts; 293 IPrimCounts pc = m_lo.PrimCounts;
294 294
295 SceneObjectGroup sogToKeep = SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1); 295 SceneObjectGroup sogToKeep = SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1);
296 sogToKeep.GroupID = m_groupId; 296 sogToKeep.GroupID = m_groupId;
297 m_scene.AddNewSceneObject(sogToKeep, false); 297 m_scene.AddNewSceneObject(sogToKeep, false);
298 298
299 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10); 299 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10);
300 m_scene.AddNewSceneObject(sogToDelete, false); 300 m_scene.AddNewSceneObject(sogToDelete, false);
301 m_scene.DeleteSceneObject(sogToDelete, false); 301 m_scene.DeleteSceneObject(sogToDelete, false);
302 302
303 Assert.That(pc.Owner, Is.EqualTo(0)); 303 Assert.That(pc.Owner, Is.EqualTo(0));
304 Assert.That(pc.Group, Is.EqualTo(1)); 304 Assert.That(pc.Group, Is.EqualTo(1));
305 Assert.That(pc.Others, Is.EqualTo(0)); 305 Assert.That(pc.Others, Is.EqualTo(0));
@@ -308,20 +308,20 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
308 Assert.That(pc.Users[m_userId], Is.EqualTo(1)); 308 Assert.That(pc.Users[m_userId], Is.EqualTo(1));
309 Assert.That(pc.Users[m_groupId], Is.EqualTo(0)); 309 Assert.That(pc.Users[m_groupId], Is.EqualTo(0));
310 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 310 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
311 Assert.That(pc.Simulator, Is.EqualTo(1)); 311 Assert.That(pc.Simulator, Is.EqualTo(1));
312 } 312 }
313 313
314 [Test] 314 [Test]
315 public void TestAddOthersObject() 315 public void TestAddOthersObject()
316 { 316 {
317 TestHelpers.InMethod(); 317 TestHelpers.InMethod();
318// log4net.Config.XmlConfigurator.Configure(); 318// log4net.Config.XmlConfigurator.Configure();
319 319
320 IPrimCounts pc = m_lo.PrimCounts; 320 IPrimCounts pc = m_lo.PrimCounts;
321 321
322 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01); 322 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01);
323 m_scene.AddNewSceneObject(sog, false); 323 m_scene.AddNewSceneObject(sog, false);
324 324
325 Assert.That(pc.Owner, Is.EqualTo(0)); 325 Assert.That(pc.Owner, Is.EqualTo(0));
326 Assert.That(pc.Group, Is.EqualTo(0)); 326 Assert.That(pc.Group, Is.EqualTo(0));
327 Assert.That(pc.Others, Is.EqualTo(3)); 327 Assert.That(pc.Others, Is.EqualTo(3));
@@ -329,22 +329,22 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
329 Assert.That(pc.Selected, Is.EqualTo(0)); 329 Assert.That(pc.Selected, Is.EqualTo(0));
330 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 330 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
331 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3)); 331 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3));
332 Assert.That(pc.Simulator, Is.EqualTo(3)); 332 Assert.That(pc.Simulator, Is.EqualTo(3));
333 } 333 }
334 334
335 [Test] 335 [Test]
336 public void TestRemoveOthersObject() 336 public void TestRemoveOthersObject()
337 { 337 {
338 TestHelpers.InMethod(); 338 TestHelpers.InMethod();
339// log4net.Config.XmlConfigurator.Configure(); 339// log4net.Config.XmlConfigurator.Configure();
340 340
341 IPrimCounts pc = m_lo.PrimCounts; 341 IPrimCounts pc = m_lo.PrimCounts;
342 342
343 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_otherUserId, "a", 0x1), false); 343 m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_otherUserId, "a", 0x1), false);
344 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_otherUserId, "b", 0x10); 344 SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_otherUserId, "b", 0x10);
345 m_scene.AddNewSceneObject(sogToDelete, false); 345 m_scene.AddNewSceneObject(sogToDelete, false);
346 m_scene.DeleteSceneObject(sogToDelete, false); 346 m_scene.DeleteSceneObject(sogToDelete, false);
347 347
348 Assert.That(pc.Owner, Is.EqualTo(0)); 348 Assert.That(pc.Owner, Is.EqualTo(0));
349 Assert.That(pc.Group, Is.EqualTo(0)); 349 Assert.That(pc.Group, Is.EqualTo(0));
350 Assert.That(pc.Others, Is.EqualTo(1)); 350 Assert.That(pc.Others, Is.EqualTo(1));
@@ -352,9 +352,9 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
352 Assert.That(pc.Selected, Is.EqualTo(0)); 352 Assert.That(pc.Selected, Is.EqualTo(0));
353 Assert.That(pc.Users[m_userId], Is.EqualTo(0)); 353 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
354 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(1)); 354 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(1));
355 Assert.That(pc.Simulator, Is.EqualTo(1)); 355 Assert.That(pc.Simulator, Is.EqualTo(1));
356 } 356 }
357 357
358 /// <summary> 358 /// <summary>
359 /// Test the count is correct after is has been tainted. 359 /// Test the count is correct after is has been tainted.
360 /// </summary> 360 /// </summary>
@@ -363,12 +363,12 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
363 { 363 {
364 TestHelpers.InMethod(); 364 TestHelpers.InMethod();
365 IPrimCounts pc = m_lo.PrimCounts; 365 IPrimCounts pc = m_lo.PrimCounts;
366 366
367 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); 367 SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01);
368 m_scene.AddNewSceneObject(sog, false); 368 m_scene.AddNewSceneObject(sog, false);
369 369
370 m_pcm.TaintPrimCount(); 370 m_pcm.TaintPrimCount();
371 371
372 Assert.That(pc.Owner, Is.EqualTo(3)); 372 Assert.That(pc.Owner, Is.EqualTo(3));
373 Assert.That(pc.Group, Is.EqualTo(0)); 373 Assert.That(pc.Group, Is.EqualTo(0));
374 Assert.That(pc.Others, Is.EqualTo(0)); 374 Assert.That(pc.Others, Is.EqualTo(0));
@@ -376,7 +376,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests
376 Assert.That(pc.Selected, Is.EqualTo(0)); 376 Assert.That(pc.Selected, Is.EqualTo(0));
377 Assert.That(pc.Users[m_userId], Is.EqualTo(3)); 377 Assert.That(pc.Users[m_userId], Is.EqualTo(3));
378 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); 378 Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0));
379 Assert.That(pc.Simulator, Is.EqualTo(3)); 379 Assert.That(pc.Simulator, Is.EqualTo(3));
380 } 380 }
381 } 381 }
382} \ No newline at end of file 382} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 796a15f..1e63662 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -73,6 +73,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
73 73
74 #region IMapImageGenerator Members 74 #region IMapImageGenerator Members
75 75
76 public Bitmap CreateMapTileForce()
77 {
78 return CreateMapTile();
79 }
76 public Bitmap CreateMapTile() 80 public Bitmap CreateMapTile()
77 { 81 {
78 bool drawPrimVolume = true; 82 bool drawPrimVolume = true;
@@ -82,11 +86,11 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
82 86
83 string[] configSections = new string[] { "Map", "Startup" }; 87 string[] configSections = new string[] { "Map", "Startup" };
84 88
85 drawPrimVolume 89 drawPrimVolume
86 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume); 90 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
87 textureTerrain 91 textureTerrain
88 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain); 92 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
89 generateMaptiles 93 generateMaptiles
90 = Util.GetConfigVarFromSections<bool>(m_config, "GenerateMaptiles", configSections, generateMaptiles); 94 = Util.GetConfigVarFromSections<bool>(m_config, "GenerateMaptiles", configSections, generateMaptiles);
91 95
92 if (generateMaptiles) 96 if (generateMaptiles)
@@ -112,7 +116,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
112 //} 116 //}
113 //t = System.Environment.TickCount - t; 117 //t = System.Environment.TickCount - t;
114 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); 118 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
115
116 if (drawPrimVolume) 119 if (drawPrimVolume)
117 { 120 {
118 DrawObjectVolume(m_scene, mapbmp); 121 DrawObjectVolume(m_scene, mapbmp);
@@ -127,15 +130,15 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
127 catch (Exception) 130 catch (Exception)
128 { 131 {
129 m_log.ErrorFormat( 132 m_log.ErrorFormat(
130 "[MAPTILE]: Failed to load Static map image texture file: {0} for {1}", 133 "[MAPTILE]: Failed to load Static map image texture file: {0} for {1}",
131 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name); 134 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name);
132 //mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 135 //mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
133 mapbmp = null; 136 mapbmp = null;
134 } 137 }
135 138
136 if (mapbmp != null) 139 if (mapbmp != null)
137 m_log.DebugFormat( 140 m_log.DebugFormat(
138 "[MAPTILE]: Static map image texture file {0} found for {1}", 141 "[MAPTILE]: Static map image texture file {0} found for {1}",
139 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name); 142 m_scene.RegionInfo.MaptileStaticFile, m_scene.Name);
140 } 143 }
141 } 144 }
@@ -309,7 +312,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
309 List<uint> z_localIDs = new List<uint>(); 312 List<uint> z_localIDs = new List<uint>();
310 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>(); 313 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
311 314
312 try 315 try
313 { 316 {
314 lock (objs) 317 lock (objs)
315 { 318 {
@@ -383,7 +386,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
383 386
384 Vector3 pos = part.GetWorldPosition(); 387 Vector3 pos = part.GetWorldPosition();
385 388
386 // skip prim outside of retion 389 // skip prim outside of region
387 if (!m_scene.PositionIsInCurrentRegion(pos)) 390 if (!m_scene.PositionIsInCurrentRegion(pos))
388 continue; 391 continue;
389 392
@@ -407,12 +410,13 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
407 { 410 {
408 // Translate scale by rotation so scale is represented properly when object is rotated 411 // Translate scale by rotation so scale is represented properly when object is rotated
409 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z); 412 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
413 lscale *= 0.5f;
414
410 Vector3 scale = new Vector3(); 415 Vector3 scale = new Vector3();
411 Vector3 tScale = new Vector3(); 416 Vector3 tScale = new Vector3();
412 Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z); 417 Vector3 axPos = new Vector3(pos.X, pos.Y, pos.Z);
413 418
414 Quaternion llrot = part.GetWorldRotation(); 419 Quaternion rot = part.GetWorldRotation();
415 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
416 scale = lscale * rot; 420 scale = lscale * rot;
417 421
418 // negative scales don't work in this situation 422 // negative scales don't work in this situation
@@ -471,7 +475,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
471 475
472 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z); 476 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
473 scale = ((tScale * rot)); 477 scale = ((tScale * rot));
474
475 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); 478 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
476 479
477 //vertexes[2].x = pos.X + vertexes[2].x; 480 //vertexes[2].x = pos.X + vertexes[2].x;
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index 708286c..0b37179 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -38,18 +38,20 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
38{ 38{
39 public class ShadedMapTileRenderer : IMapTileTerrainRenderer 39 public class ShadedMapTileRenderer : IMapTileTerrainRenderer
40 { 40 {
41 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
42
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]"; 42 private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]";
45 43
46 private Scene m_scene; 44 private Scene m_scene;
47 //private IConfigSource m_config; // not used currently 45 private IConfigSource m_config;
46 private Color m_color_water;
48 47
49 public void Initialise(Scene scene, IConfigSource config) 48 public void Initialise(Scene scene, IConfigSource config)
50 { 49 {
51 m_scene = scene; 50 m_scene = scene;
52 // m_config = config; // not used currently 51 m_config = config;
52
53 string[] configSections = new string[] { "Map", "Startup" };
54 m_color_water = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColorWater", configSections, "#1D475F"));
53 } 55 }
54 56
55 public void TerrainToBitmap(Bitmap mapbmp) 57 public void TerrainToBitmap(Bitmap mapbmp)
@@ -231,7 +233,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
231 233
232 try 234 try
233 { 235 {
234 mapbmp.SetPixel(x, yr, WATER_COLOR); 236 mapbmp.SetPixel(x, yr, m_color_water);
235 } 237 }
236 catch (ArgumentException) 238 catch (ArgumentException)
237 { 239 {
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index 9f23141..c71f5c0 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -130,21 +130,19 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
130 // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank"). 130 // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank").
131 // The color-values were choosen because they "look right" (at least to me) ;-) 131 // The color-values were choosen because they "look right" (at least to me) ;-)
132 private static readonly UUID defaultTerrainTexture1 = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5"); 132 private static readonly UUID defaultTerrainTexture1 = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5");
133 private static readonly Color defaultColor1 = Color.FromArgb(165, 137, 118);
134 private static readonly UUID defaultTerrainTexture2 = new UUID("63338ede-0037-c4fd-855b-015d77112fc8"); 133 private static readonly UUID defaultTerrainTexture2 = new UUID("63338ede-0037-c4fd-855b-015d77112fc8");
135 private static readonly Color defaultColor2 = Color.FromArgb(69, 89, 49);
136 private static readonly UUID defaultTerrainTexture3 = new UUID("303cd381-8560-7579-23f1-f0a880799740"); 134 private static readonly UUID defaultTerrainTexture3 = new UUID("303cd381-8560-7579-23f1-f0a880799740");
137 private static readonly Color defaultColor3 = Color.FromArgb(162, 154, 141);
138 private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c"); 135 private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c");
139 private static readonly Color defaultColor4 = Color.FromArgb(200, 200, 200);
140
141 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
142 136
143 #endregion 137 #endregion
144 138
145
146 private Scene m_scene; 139 private Scene m_scene;
147 // private IConfigSource m_config; // not used currently 140 private IConfigSource m_config;
141 private Color m_color_water;
142 private Color m_color_1;
143 private Color m_color_2;
144 private Color m_color_3;
145 private Color m_color_4;
148 146
149 // mapping from texture UUIDs to averaged color. This will contain 5-9 values, in general; new values are only 147 // mapping from texture UUIDs to averaged color. This will contain 5-9 values, in general; new values are only
150 // added when the terrain textures are changed in the estate dialog and a new map is generated (and will stay in 148 // added when the terrain textures are changed in the estate dialog and a new map is generated (and will stay in
@@ -156,12 +154,21 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
156 public void Initialise(Scene scene, IConfigSource source) 154 public void Initialise(Scene scene, IConfigSource source)
157 { 155 {
158 m_scene = scene; 156 m_scene = scene;
159 // m_config = source; // not used currently 157 m_config = source;
158
159 string[] configSections = new string[] { "Map", "Startup" };
160
161 m_color_water = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColorWater", configSections, "#1D475F"));
162 m_color_1 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor1", configSections, "#A58976"));
163 m_color_2 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor2", configSections, "#455931"));
164 m_color_3 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor3", configSections, "#A29A8D"));
165 m_color_4 = System.Drawing.ColorTranslator.FromHtml(Util.GetConfigVarFromSections<string>(m_config, "MapColor4", configSections, "#C8C8C8"));
166
160 m_mapping = new Dictionary<UUID,Color>(); 167 m_mapping = new Dictionary<UUID,Color>();
161 m_mapping.Add(defaultTerrainTexture1, defaultColor1); 168 m_mapping.Add(defaultTerrainTexture1, m_color_1);
162 m_mapping.Add(defaultTerrainTexture2, defaultColor2); 169 m_mapping.Add(defaultTerrainTexture2, m_color_2);
163 m_mapping.Add(defaultTerrainTexture3, defaultColor3); 170 m_mapping.Add(defaultTerrainTexture3, m_color_3);
164 m_mapping.Add(defaultTerrainTexture4, defaultColor4); 171 m_mapping.Add(defaultTerrainTexture4, m_color_4);
165 m_mapping.Add(Util.BLANK_TEXTURE_UUID, Color.White); 172 m_mapping.Add(Util.BLANK_TEXTURE_UUID, Color.White);
166 } 173 }
167 174
@@ -180,7 +187,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
180 187
181 ManagedImage managedImage; 188 ManagedImage managedImage;
182 Image image; 189 Image image;
183 190
184 try 191 try
185 { 192 {
186 if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image)) 193 if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image))
@@ -201,7 +208,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
201 m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id); 208 m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id);
202 } 209 }
203 return null; 210 return null;
204 211
205 } 212 }
206 213
207 // Compute the average color of a texture. 214 // Compute the average color of a texture.
@@ -288,7 +295,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
288 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height) 295 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
289 { 296 {
290 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>", 297 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); 298 "[TEXTURED MAP TILE RENDERER]", mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
292 } 299 }
293 300
294 // These textures should be in the AssetCache anyway, as every client conneting to this 301 // These textures should be in the AssetCache anyway, as every client conneting to this
@@ -298,10 +305,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
298 RegionSettings settings = m_scene.RegionInfo.RegionSettings; 305 RegionSettings settings = m_scene.RegionInfo.RegionSettings;
299 306
300 // the four terrain colors as HSVs for interpolation 307 // the four terrain colors as HSVs for interpolation
301 HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, defaultColor1)); 308 HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, m_color_1));
302 HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, defaultColor2)); 309 HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, m_color_2));
303 HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, defaultColor3)); 310 HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, m_color_3));
304 HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, defaultColor4)); 311 HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, m_color_4));
305 312
306 float levelNElow = (float)settings.Elevation1NE; 313 float levelNElow = (float)settings.Elevation1NE;
307 float levelNEhigh = (float)settings.Elevation2NE; 314 float levelNEhigh = (float)settings.Elevation2NE;
@@ -371,8 +378,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
371 // first, rescale h to 0.0 - 1.0 378 // first, rescale h to 0.0 - 1.0
372 hmod = (hmod - low) / (high - low); 379 hmod = (hmod - low) / (high - low);
373 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 380 // 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); 381 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); 382 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); 383 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f);
377 } 384 }
378 385
@@ -417,7 +424,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
417 424
418 heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0 425 heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0
419 426
420 mapbmp.SetPixel(x, yr, WATER_COLOR); 427 mapbmp.SetPixel(x, yr, m_color_water);
421 } 428 }
422 } 429 }
423 } 430 }
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/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
index 46b0470..f5aa40a 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
56 public class MoapModule : INonSharedRegionModule, IMoapModule 56 public class MoapModule : INonSharedRegionModule, IMoapModule
57 { 57 {
58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 59
60 public string Name { get { return "MoapModule"; } } 60 public string Name { get { return "MoapModule"; } }
61 public Type ReplaceableInterface { get { return null; } } 61 public Type ReplaceableInterface { get { return null; } }
62 62
@@ -64,33 +64,33 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
64 /// Is this module enabled? 64 /// Is this module enabled?
65 /// </summary> 65 /// </summary>
66 protected bool m_isEnabled = true; 66 protected bool m_isEnabled = true;
67 67
68 /// <summary> 68 /// <summary>
69 /// The scene to which this module is attached 69 /// The scene to which this module is attached
70 /// </summary> 70 /// </summary>
71 protected Scene m_scene; 71 protected Scene m_scene;
72 72
73 /// <summary> 73 /// <summary>
74 /// Track the ObjectMedia capabilities given to users keyed by path 74 /// Track the ObjectMedia capabilities given to users keyed by path
75 /// </summary> 75 /// </summary>
76 protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>(); 76 protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>();
77 77
78 /// <summary> 78 /// <summary>
79 /// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate. 79 /// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate.
80 /// </summary> 80 /// </summary>
81 protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>(); 81 protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>();
82 82
83 /// <summary> 83 /// <summary>
84 /// Track the ObjectMediaUpdate capabilities given to users keyed by path 84 /// Track the ObjectMediaUpdate capabilities given to users keyed by path
85 /// </summary> 85 /// </summary>
86 protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>(); 86 protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>();
87 87
88 /// <summary> 88 /// <summary>
89 /// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate 89 /// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate
90 /// </summary> 90 /// </summary>
91 protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>(); 91 protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>();
92 92
93 public void Initialise(IConfigSource configSource) 93 public void Initialise(IConfigSource configSource)
94 { 94 {
95 IConfig config = configSource.Configs["MediaOnAPrim"]; 95 IConfig config = configSource.Configs["MediaOnAPrim"];
96 96
@@ -100,63 +100,63 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
100// m_log.Debug("[MOAP]: Initialised module.")l 100// m_log.Debug("[MOAP]: Initialised module.")l
101 } 101 }
102 102
103 public void AddRegion(Scene scene) 103 public void AddRegion(Scene scene)
104 { 104 {
105 if (!m_isEnabled) 105 if (!m_isEnabled)
106 return; 106 return;
107 107
108 m_scene = scene; 108 m_scene = scene;
109 m_scene.RegisterModuleInterface<IMoapModule>(this); 109 m_scene.RegisterModuleInterface<IMoapModule>(this);
110 } 110 }
111 111
112 public void RemoveRegion(Scene scene) {} 112 public void RemoveRegion(Scene scene) {}
113 113
114 public void RegionLoaded(Scene scene) 114 public void RegionLoaded(Scene scene)
115 { 115 {
116 if (!m_isEnabled) 116 if (!m_isEnabled)
117 return; 117 return;
118 118
119 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 119 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
120 m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps; 120 m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps;
121 m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy; 121 m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy;
122 } 122 }
123 123
124 public void Close() 124 public void Close()
125 { 125 {
126 if (!m_isEnabled) 126 if (!m_isEnabled)
127 return; 127 return;
128 128
129 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 129 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
130 m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps; 130 m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps;
131 m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy; 131 m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy;
132 } 132 }
133 133
134 public void OnRegisterCaps(UUID agentID, Caps caps) 134 public void OnRegisterCaps(UUID agentID, Caps caps)
135 { 135 {
136// m_log.DebugFormat( 136// m_log.DebugFormat(
137// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID); 137// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID);
138 138
139 string omCapUrl = "/CAPS/" + UUID.Random(); 139 string omCapUrl = "/CAPS/" + UUID.Random();
140 140
141 lock (m_omCapUsers) 141 lock (m_omCapUsers)
142 { 142 {
143 m_omCapUsers[omCapUrl] = agentID; 143 m_omCapUsers[omCapUrl] = agentID;
144 m_omCapUrls[agentID] = omCapUrl; 144 m_omCapUrls[agentID] = omCapUrl;
145 145
146 // Even though we're registering for POST we're going to get GETS and UPDATES too 146 // Even though we're registering for POST we're going to get GETS and UPDATES too
147 caps.RegisterHandler( 147 caps.RegisterHandler(
148 "ObjectMedia", 148 "ObjectMedia",
149 new RestStreamHandler( 149 new RestStreamHandler(
150 "POST", omCapUrl, HandleObjectMediaMessage, "ObjectMedia", agentID.ToString())); 150 "POST", omCapUrl, HandleObjectMediaMessage, "ObjectMedia", agentID.ToString()));
151 } 151 }
152 152
153 string omuCapUrl = "/CAPS/" + UUID.Random(); 153 string omuCapUrl = "/CAPS/" + UUID.Random();
154 154
155 lock (m_omuCapUsers) 155 lock (m_omuCapUsers)
156 { 156 {
157 m_omuCapUsers[omuCapUrl] = agentID; 157 m_omuCapUsers[omuCapUrl] = agentID;
158 m_omuCapUrls[agentID] = omuCapUrl; 158 m_omuCapUrls[agentID] = omuCapUrl;
159 159
160 // Even though we're registering for POST we're going to get GETS and UPDATES too 160 // Even though we're registering for POST we're going to get GETS and UPDATES too
161 caps.RegisterHandler( 161 caps.RegisterHandler(
162 "ObjectMediaNavigate", 162 "ObjectMediaNavigate",
@@ -164,7 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
164 "POST", omuCapUrl, HandleObjectMediaNavigateMessage, "ObjectMediaNavigate", agentID.ToString())); 164 "POST", omuCapUrl, HandleObjectMediaNavigateMessage, "ObjectMediaNavigate", agentID.ToString()));
165 } 165 }
166 } 166 }
167 167
168 public void OnDeregisterCaps(UUID agentID, Caps caps) 168 public void OnDeregisterCaps(UUID agentID, Caps caps)
169 { 169 {
170 lock (m_omCapUsers) 170 lock (m_omCapUsers)
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
173 m_omCapUrls.Remove(agentID); 173 m_omCapUrls.Remove(agentID);
174 m_omCapUsers.Remove(path); 174 m_omCapUsers.Remove(path);
175 } 175 }
176 176
177 lock (m_omuCapUsers) 177 lock (m_omuCapUsers)
178 { 178 {
179 string path = m_omuCapUrls[agentID]; 179 string path = m_omuCapUrls[agentID];
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
181 m_omuCapUsers.Remove(path); 181 m_omuCapUsers.Remove(path);
182 } 182 }
183 } 183 }
184 184
185 protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed) 185 protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
186 { 186 {
187 if (original.Shape.Media != null) 187 if (original.Shape.Media != null)
@@ -197,19 +197,19 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
197 dupeMedia.Add(null); 197 dupeMedia.Add(null);
198 } 198 }
199 } 199 }
200 200
201 copy.Shape.Media = dupeMedia; 201 copy.Shape.Media = dupeMedia;
202 } 202 }
203 } 203 }
204 204
205 public MediaEntry GetMediaEntry(SceneObjectPart part, int face) 205 public MediaEntry GetMediaEntry(SceneObjectPart part, int face)
206 { 206 {
207 MediaEntry me = null; 207 MediaEntry me = null;
208 208
209 CheckFaceParam(part, face); 209 CheckFaceParam(part, face);
210 210
211 List<MediaEntry> media = part.Shape.Media; 211 List<MediaEntry> media = part.Shape.Media;
212 212
213 if (null == media) 213 if (null == media)
214 { 214 {
215 me = null; 215 me = null;
@@ -218,17 +218,17 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
218 { 218 {
219 lock (media) 219 lock (media)
220 me = media[face]; 220 me = media[face];
221 221
222 // TODO: Really need a proper copy constructor down in libopenmetaverse 222 // TODO: Really need a proper copy constructor down in libopenmetaverse
223 if (me != null) 223 if (me != null)
224 me = MediaEntry.FromOSD(me.GetOSD()); 224 me = MediaEntry.FromOSD(me.GetOSD());
225 } 225 }
226 226
227// m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me); 227// m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me);
228 228
229 return me; 229 return me;
230 } 230 }
231 231
232 /// <summary> 232 /// <summary>
233 /// Set the media entry on the face of the given part. 233 /// Set the media entry on the face of the given part.
234 /// </summary> 234 /// </summary>
@@ -238,28 +238,29 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
238 public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) 238 public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me)
239 { 239 {
240// m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face); 240// m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face);
241 241
242 CheckFaceParam(part, face); 242 CheckFaceParam(part, face);
243 243
244 if (null == part.Shape.Media) 244 if (null == part.Shape.Media)
245 { 245 {
246 if (me == null) 246 if (me == null)
247 return; 247 return;
248 else 248 else
249 part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]); 249 part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
250 } 250 }
251 251
252 lock (part.Shape.Media) 252 lock (part.Shape.Media)
253 part.Shape.Media[face] = me; 253 part.Shape.Media[face] = me;
254 254
255 UpdateMediaUrl(part, UUID.Zero); 255 UpdateMediaUrl(part, UUID.Zero);
256 256
257 SetPartMediaFlags(part, face, me != null); 257 SetPartMediaFlags(part, face, me != null);
258 258
259 part.ParentGroup.HasGroupChanged = true;
259 part.ScheduleFullUpdate(); 260 part.ScheduleFullUpdate();
260 part.TriggerScriptChangedEvent(Changed.MEDIA); 261 part.TriggerScriptChangedEvent(Changed.MEDIA);
261 } 262 }
262 263
263 /// <summary> 264 /// <summary>
264 /// Clear the media entry from the face of the given part. 265 /// Clear the media entry from the face of the given part.
265 /// </summary> 266 /// </summary>
@@ -267,9 +268,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
267 /// <param name="face"></param> 268 /// <param name="face"></param>
268 public void ClearMediaEntry(SceneObjectPart part, int face) 269 public void ClearMediaEntry(SceneObjectPart part, int face)
269 { 270 {
270 SetMediaEntry(part, face, null); 271 SetMediaEntry(part, face, null);
271 } 272 }
272 273
273 /// <summary> 274 /// <summary>
274 /// Set the media flags on the texture face of the given part. 275 /// Set the media flags on the texture face of the given part.
275 /// </summary> 276 /// </summary>
@@ -284,9 +285,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
284 Primitive.TextureEntry te = part.Shape.Textures; 285 Primitive.TextureEntry te = part.Shape.Textures;
285 Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); 286 Primitive.TextureEntryFace teFace = te.CreateFace((uint)face);
286 teFace.MediaFlags = flag; 287 teFace.MediaFlags = flag;
287 part.Shape.Textures = te; 288 part.Shape.Textures = te;
288 } 289 }
289 290
290 /// <summary> 291 /// <summary>
291 /// Sets or gets per face media textures. 292 /// Sets or gets per face media textures.
292 /// </summary> 293 /// </summary>
@@ -300,11 +301,11 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
300 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 301 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
301 { 302 {
302// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request); 303// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request);
303 304
304 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request); 305 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
305 ObjectMediaMessage omm = new ObjectMediaMessage(); 306 ObjectMediaMessage omm = new ObjectMediaMessage();
306 omm.Deserialize(osd); 307 omm.Deserialize(osd);
307 308
308 if (omm.Request is ObjectMediaRequest) 309 if (omm.Request is ObjectMediaRequest)
309 return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest); 310 return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest);
310 else if (omm.Request is ObjectMediaUpdate) 311 else if (omm.Request is ObjectMediaUpdate)
@@ -312,10 +313,10 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
312 313
313 throw new Exception( 314 throw new Exception(
314 string.Format( 315 string.Format(
315 "[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}", 316 "[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}",
316 omm.Request.GetType())); 317 omm.Request.GetType()));
317 } 318 }
318 319
319 /// <summary> 320 /// <summary>
320 /// Handle a fetch request for media textures 321 /// Handle a fetch request for media textures
321 /// </summary> 322 /// </summary>
@@ -324,36 +325,36 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
324 protected string HandleObjectMediaRequest(ObjectMediaRequest omr) 325 protected string HandleObjectMediaRequest(ObjectMediaRequest omr)
325 { 326 {
326 UUID primId = omr.PrimID; 327 UUID primId = omr.PrimID;
327 328
328 SceneObjectPart part = m_scene.GetSceneObjectPart(primId); 329 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
329 330
330 if (null == part) 331 if (null == part)
331 { 332 {
332 m_log.WarnFormat( 333 m_log.WarnFormat(
333 "[MOAP]: Received a GET ObjectMediaRequest for prim {0} but this doesn't exist in region {1}", 334 "[MOAP]: Received a GET ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
334 primId, m_scene.RegionInfo.RegionName); 335 primId, m_scene.RegionInfo.RegionName);
335 return string.Empty; 336 return string.Empty;
336 } 337 }
337 338
338 if (null == part.Shape.Media) 339 if (null == part.Shape.Media)
339 return string.Empty; 340 return string.Empty;
340 341
341 ObjectMediaResponse resp = new ObjectMediaResponse(); 342 ObjectMediaResponse resp = new ObjectMediaResponse();
342 343
343 resp.PrimID = primId; 344 resp.PrimID = primId;
344 345
345 lock (part.Shape.Media) 346 lock (part.Shape.Media)
346 resp.FaceMedia = part.Shape.Media.ToArray(); 347 resp.FaceMedia = part.Shape.Media.ToArray();
347 348
348 resp.Version = part.MediaUrl; 349 resp.Version = part.MediaUrl;
349 350
350 string rawResp = OSDParser.SerializeLLSDXmlString(resp.Serialize()); 351 string rawResp = OSDParser.SerializeLLSDXmlString(resp.Serialize());
351 352
352// m_log.DebugFormat("[MOAP]: Got HandleObjectMediaRequestGet raw response is [{0}]", rawResp); 353// m_log.DebugFormat("[MOAP]: Got HandleObjectMediaRequestGet raw response is [{0}]", rawResp);
353 354
354 return rawResp; 355 return rawResp;
355 } 356 }
356 357
357 /// <summary> 358 /// <summary>
358 /// Handle an update of media textures. 359 /// Handle an update of media textures.
359 /// </summary> 360 /// </summary>
@@ -363,46 +364,46 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
363 protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu) 364 protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu)
364 { 365 {
365 UUID primId = omu.PrimID; 366 UUID primId = omu.PrimID;
366 367
367 SceneObjectPart part = m_scene.GetSceneObjectPart(primId); 368 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
368 369
369 if (null == part) 370 if (null == part)
370 { 371 {
371 m_log.WarnFormat( 372 m_log.WarnFormat(
372 "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}", 373 "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
373 primId, m_scene.RegionInfo.RegionName); 374 primId, m_scene.RegionInfo.RegionName);
374 return string.Empty; 375 return string.Empty;
375 } 376 }
376 377
377// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId); 378// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);
378// 379//
379// for (int i = 0; i < omu.FaceMedia.Length; i++) 380// for (int i = 0; i < omu.FaceMedia.Length; i++)
380// { 381// {
381// MediaEntry me = omu.FaceMedia[i]; 382// MediaEntry me = omu.FaceMedia[i];
382// string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD())); 383// string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD()));
383// m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v); 384// m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v);
384// } 385// }
385 386
386 if (omu.FaceMedia.Length > part.GetNumberOfSides()) 387 if (omu.FaceMedia.Length > part.GetNumberOfSides())
387 { 388 {
388 m_log.WarnFormat( 389 m_log.WarnFormat(
389 "[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.", 390 "[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.",
390 omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides()); 391 omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
391 return string.Empty; 392 return string.Empty;
392 } 393 }
393 394
394 UUID agentId = default(UUID); 395 UUID agentId = default(UUID);
395 396
396 lock (m_omCapUsers) 397 lock (m_omCapUsers)
397 agentId = m_omCapUsers[path]; 398 agentId = m_omCapUsers[path];
398 399
399 List<MediaEntry> media = part.Shape.Media; 400 List<MediaEntry> media = part.Shape.Media;
400 401
401 if (null == media) 402 if (null == media)
402 { 403 {
403// m_log.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name); 404// m_log.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name);
404 part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia); 405 part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia);
405 406
406 for (int i = 0; i < omu.FaceMedia.Length; i++) 407 for (int i = 0; i < omu.FaceMedia.Length; i++)
407 { 408 {
408 if (omu.FaceMedia[i] != null) 409 if (omu.FaceMedia[i] != null)
@@ -412,7 +413,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
412 // directly. 413 // directly.
413 SetPartMediaFlags(part, i, true); 414 SetPartMediaFlags(part, i, true);
414// m_log.DebugFormat( 415// m_log.DebugFormat(
415// "[MOAP]: Media flags for face {0} is {1}", 416// "[MOAP]: Media flags for face {0} is {1}",
416// i, part.Shape.Textures.FaceTextures[i].MediaFlags); 417// i, part.Shape.Textures.FaceTextures[i].MediaFlags);
417 } 418 }
418 } 419 }
@@ -420,15 +421,15 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
420 else 421 else
421 { 422 {
422// m_log.DebugFormat("[MOAP]: Setting existing media list for {0}", part.Name); 423// m_log.DebugFormat("[MOAP]: Setting existing media list for {0}", part.Name);
423 424
424 // We need to go through the media textures one at a time to make sure that we have permission 425 // We need to go through the media textures one at a time to make sure that we have permission
425 // to change them 426 // to change them
426 427
427 // FIXME: Race condition here since some other texture entry manipulator may overwrite/get 428 // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
428 // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry 429 // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
429 // directly. 430 // directly.
430 Primitive.TextureEntry te = part.Shape.Textures; 431 Primitive.TextureEntry te = part.Shape.Textures;
431 432
432 lock (media) 433 lock (media)
433 { 434 {
434 for (int i = 0; i < media.Count; i++) 435 for (int i = 0; i < media.Count; i++)
@@ -436,38 +437,39 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
436 if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i)) 437 if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i))
437 { 438 {
438 media[i] = omu.FaceMedia[i]; 439 media[i] = omu.FaceMedia[i];
439 440
440 // When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal 441 // When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal
441 // texture update, so we don't need to worry about clearing MediaFlags here. 442 // texture update, so we don't need to worry about clearing MediaFlags here.
442 if (null == media[i]) 443 if (null == media[i])
443 continue; 444 continue;
444 445
445 SetPartMediaFlags(part, i, true); 446 SetPartMediaFlags(part, i, true);
446 447
447 // m_log.DebugFormat( 448 // m_log.DebugFormat(
448 // "[MOAP]: Media flags for face {0} is {1}", 449 // "[MOAP]: Media flags for face {0} is {1}",
449 // i, face.MediaFlags); 450 // i, face.MediaFlags);
450 // m_log.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name); 451 // m_log.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name);
451 } 452 }
452 } 453 }
453 } 454 }
454 455
455 part.Shape.Textures = te; 456 part.Shape.Textures = te;
456 457
457// for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++) 458// for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++)
458// m_log.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]); 459// m_log.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]);
459 } 460 }
460 461
461 UpdateMediaUrl(part, agentId); 462 UpdateMediaUrl(part, agentId);
462 463
463 // Arguably, we could avoid sending a full update to the avatar that just changed the texture. 464 // Arguably, we could avoid sending a full update to the avatar that just changed the texture.
465 part.ParentGroup.HasGroupChanged = true;
464 part.ScheduleFullUpdate(); 466 part.ScheduleFullUpdate();
465 467
466 part.TriggerScriptChangedEvent(Changed.MEDIA); 468 part.TriggerScriptChangedEvent(Changed.MEDIA);
467 469
468 return string.Empty; 470 return string.Empty;
469 } 471 }
470 472
471 /// <summary> 473 /// <summary>
472 /// Received from the viewer if a user has changed the url of a media texture. 474 /// Received from the viewer if a user has changed the url of a media texture.
473 /// </summary> 475 /// </summary>
@@ -481,71 +483,72 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
481 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 483 string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
482 { 484 {
483// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request); 485// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);
484 486
485 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request); 487 OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
486 ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage(); 488 ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();
487 omn.Deserialize(osd); 489 omn.Deserialize(osd);
488 490
489 UUID primId = omn.PrimID; 491 UUID primId = omn.PrimID;
490 492
491 SceneObjectPart part = m_scene.GetSceneObjectPart(primId); 493 SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
492 494
493 if (null == part) 495 if (null == part)
494 { 496 {
495 m_log.WarnFormat( 497 m_log.WarnFormat(
496 "[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}", 498 "[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
497 primId, m_scene.RegionInfo.RegionName); 499 primId, m_scene.RegionInfo.RegionName);
498 return string.Empty; 500 return string.Empty;
499 } 501 }
500 502
501 UUID agentId = default(UUID); 503 UUID agentId = default(UUID);
502 504
503 lock (m_omuCapUsers) 505 lock (m_omuCapUsers)
504 agentId = m_omuCapUsers[path]; 506 agentId = m_omuCapUsers[path];
505 507
506 if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face)) 508 if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
507 return string.Empty; 509 return string.Empty;
508 510
509// m_log.DebugFormat( 511// m_log.DebugFormat(
510// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}", 512// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
511// omn.Face, part.Name, part.UUID, omn.URL); 513// omn.Face, part.Name, part.UUID, omn.URL);
512 514
513 // If media has never been set for this prim, then just return. 515 // If media has never been set for this prim, then just return.
514 if (null == part.Shape.Media) 516 if (null == part.Shape.Media)
515 return string.Empty; 517 return string.Empty;
516 518
517 MediaEntry me = null; 519 MediaEntry me = null;
518 520
519 lock (part.Shape.Media) 521 lock (part.Shape.Media)
520 me = part.Shape.Media[omn.Face]; 522 me = part.Shape.Media[omn.Face];
521 523
522 // Do the same if media has not been set up for a specific face 524 // Do the same if media has not been set up for a specific face
523 if (null == me) 525 if (null == me)
524 return string.Empty; 526 return string.Empty;
525 527
526 if (me.EnableWhiteList) 528 if (me.EnableWhiteList)
527 { 529 {
528 if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList)) 530 if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
529 { 531 {
530// m_log.DebugFormat( 532// m_log.DebugFormat(
531// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist", 533// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
532// omn.Face, part.Name, part.UUID, omn.URL); 534// omn.Face, part.Name, part.UUID, omn.URL);
533 535
534 return string.Empty; 536 return string.Empty;
535 } 537 }
536 } 538 }
537 539
538 me.CurrentURL = omn.URL; 540 me.CurrentURL = omn.URL;
539 541
540 UpdateMediaUrl(part, agentId); 542 UpdateMediaUrl(part, agentId);
541 543
544 part.ParentGroup.HasGroupChanged = true;
542 part.ScheduleFullUpdate(); 545 part.ScheduleFullUpdate();
543 546
544 part.TriggerScriptChangedEvent(Changed.MEDIA); 547 part.TriggerScriptChangedEvent(Changed.MEDIA);
545 548
546 return OSDParser.SerializeLLSDXmlString(new OSD()); 549 return OSDParser.SerializeLLSDXmlString(new OSD());
547 } 550 }
548 551
549 /// <summary> 552 /// <summary>
550 /// Check that the face number is valid for the given prim. 553 /// Check that the face number is valid for the given prim.
551 /// </summary> 554 /// </summary>
@@ -555,13 +558,13 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
555 { 558 {
556 if (face < 0) 559 if (face < 0)
557 throw new ArgumentException("Face cannot be less than zero"); 560 throw new ArgumentException("Face cannot be less than zero");
558 561
559 int maxFaces = part.GetNumberOfSides() - 1; 562 int maxFaces = part.GetNumberOfSides() - 1;
560 if (face > maxFaces) 563 if (face > maxFaces)
561 throw new ArgumentException( 564 throw new ArgumentException(
562 string.Format("Face argument was {0} but max is {1}", face, maxFaces)); 565 string.Format("Face argument was {0} but max is {1}", face, maxFaces));
563 } 566 }
564 567
565 /// <summary> 568 /// <summary>
566 /// Update the media url of the given part 569 /// Update the media url of the given part
567 /// </summary> 570 /// </summary>
@@ -583,10 +586,10 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
583 int version = int.Parse(rawVersion); 586 int version = int.Parse(rawVersion);
584 part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId); 587 part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId);
585 } 588 }
586 589
587// m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID); 590// m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
588 } 591 }
589 592
590 /// <summary> 593 /// <summary>
591 /// Check the given url against the given whitelist. 594 /// Check the given url against the given whitelist.
592 /// </summary> 595 /// </summary>
@@ -599,22 +602,22 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
599 return false; 602 return false;
600 603
601 Uri url = new Uri(rawUrl); 604 Uri url = new Uri(rawUrl);
602 605
603 foreach (string origWlUrl in whitelist) 606 foreach (string origWlUrl in whitelist)
604 { 607 {
605 string wlUrl = origWlUrl; 608 string wlUrl = origWlUrl;
606 609
607 // Deal with a line-ending wildcard 610 // Deal with a line-ending wildcard
608 if (wlUrl.EndsWith("*")) 611 if (wlUrl.EndsWith("*"))
609 wlUrl = wlUrl.Remove(wlUrl.Length - 1); 612 wlUrl = wlUrl.Remove(wlUrl.Length - 1);
610 613
611// m_log.DebugFormat("[MOAP]: Checking whitelist URL pattern {0}", origWlUrl); 614// m_log.DebugFormat("[MOAP]: Checking whitelist URL pattern {0}", origWlUrl);
612 615
613 // Handle a line starting wildcard slightly differently since this can only match the domain, not the path 616 // Handle a line starting wildcard slightly differently since this can only match the domain, not the path
614 if (wlUrl.StartsWith("*")) 617 if (wlUrl.StartsWith("*"))
615 { 618 {
616 wlUrl = wlUrl.Substring(1); 619 wlUrl = wlUrl.Substring(1);
617 620
618 if (url.Host.Contains(wlUrl)) 621 if (url.Host.Contains(wlUrl))
619 { 622 {
620// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl); 623// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
@@ -624,7 +627,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
624 else 627 else
625 { 628 {
626 string urlToMatch = url.Authority + url.AbsolutePath; 629 string urlToMatch = url.Authority + url.AbsolutePath;
627 630
628 if (urlToMatch.StartsWith(wlUrl)) 631 if (urlToMatch.StartsWith(wlUrl))
629 { 632 {
630// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl); 633// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
@@ -632,7 +635,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
632 } 635 }
633 } 636 }
634 } 637 }
635 638
636 return false; 639 return false;
637 } 640 }
638 } 641 }
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
index ee57aed..7080705 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
47 { 47 {
48 protected TestScene m_scene; 48 protected TestScene m_scene;
49 protected MoapModule m_module; 49 protected MoapModule m_module;
50 50
51 [SetUp] 51 [SetUp]
52 public override void SetUp() 52 public override void SetUp()
53 { 53 {
@@ -55,45 +55,45 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
55 55
56 m_module = new MoapModule(); 56 m_module = new MoapModule();
57 m_scene = new SceneHelpers().SetupScene(); 57 m_scene = new SceneHelpers().SetupScene();
58 SceneHelpers.SetupSceneModules(m_scene, m_module); 58 SceneHelpers.SetupSceneModules(m_scene, m_module);
59 } 59 }
60 60
61 [Test] 61 [Test]
62 public void TestClearMediaUrl() 62 public void TestClearMediaUrl()
63 { 63 {
64 TestHelpers.InMethod(); 64 TestHelpers.InMethod();
65// log4net.Config.XmlConfigurator.Configure(); 65// log4net.Config.XmlConfigurator.Configure();
66 66
67 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 67 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
68 MediaEntry me = new MediaEntry(); 68 MediaEntry me = new MediaEntry();
69 69
70 m_module.SetMediaEntry(part, 1, me); 70 m_module.SetMediaEntry(part, 1, me);
71 m_module.ClearMediaEntry(part, 1); 71 m_module.ClearMediaEntry(part, 1);
72 72
73 Assert.That(part.Shape.Media[1], Is.EqualTo(null)); 73 Assert.That(part.Shape.Media[1], Is.EqualTo(null));
74 74
75 // Although we've cleared one face, other faces may still be present. So we need to check for an 75 // Although we've cleared one face, other faces may still be present. So we need to check for an
76 // update media url version 76 // update media url version
77 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000001/" + UUID.Zero)); 77 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000001/" + UUID.Zero));
78 78
79 // By changing media flag to false, the face texture once again becomes identical to the DefaultTexture. 79 // By changing media flag to false, the face texture once again becomes identical to the DefaultTexture.
80 // Therefore, when libOMV reserializes it, it disappears and we are left with no face texture in this slot. 80 // Therefore, when libOMV reserializes it, it disappears and we are left with no face texture in this slot.
81 // Not at all confusing, eh? 81 // Not at all confusing, eh?
82 Assert.That(part.Shape.Textures.FaceTextures[1], Is.Null); 82 Assert.That(part.Shape.Textures.FaceTextures[1], Is.Null);
83 } 83 }
84 84
85 [Test] 85 [Test]
86 public void TestSetMediaUrl() 86 public void TestSetMediaUrl()
87 { 87 {
88 TestHelpers.InMethod(); 88 TestHelpers.InMethod();
89 89
90 string homeUrl = "opensimulator.org"; 90 string homeUrl = "opensimulator.org";
91 91
92 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 92 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
93 MediaEntry me = new MediaEntry() { HomeURL = homeUrl }; 93 MediaEntry me = new MediaEntry() { HomeURL = homeUrl };
94 94
95 m_module.SetMediaEntry(part, 1, me); 95 m_module.SetMediaEntry(part, 1, me);
96 96
97 Assert.That(part.Shape.Media[1].HomeURL, Is.EqualTo(homeUrl)); 97 Assert.That(part.Shape.Media[1].HomeURL, Is.EqualTo(homeUrl));
98 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000000/" + UUID.Zero)); 98 Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000000/" + UUID.Zero));
99 Assert.That(part.Shape.Textures.FaceTextures[1].MediaFlags, Is.True); 99 Assert.That(part.Shape.Textures.FaceTextures[1].MediaFlags, Is.True);
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 2abc910..6a8f4c0 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -45,38 +45,38 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BuySellModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BuySellModule")]
46 public class BuySellModule : IBuySellModule, INonSharedRegionModule 46 public class BuySellModule : IBuySellModule, INonSharedRegionModule
47 { 47 {
48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 protected Scene m_scene = null; 50 protected Scene m_scene = null;
51 protected IDialogModule m_dialogModule; 51 protected IDialogModule m_dialogModule;
52 52
53 public string Name { get { return "Object BuySell Module"; } } 53 public string Name { get { return "Object BuySell Module"; } }
54 public Type ReplaceableInterface { get { return null; } } 54 public Type ReplaceableInterface { get { return null; } }
55 55
56 public void Initialise(IConfigSource source) {} 56 public void Initialise(IConfigSource source) {}
57 57
58 public void AddRegion(Scene scene) 58 public void AddRegion(Scene scene)
59 { 59 {
60 m_scene = scene; 60 m_scene = scene;
61 m_scene.RegisterModuleInterface<IBuySellModule>(this); 61 m_scene.RegisterModuleInterface<IBuySellModule>(this);
62 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 62 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
63 } 63 }
64 64
65 public void RemoveRegion(Scene scene) 65 public void RemoveRegion(Scene scene)
66 { 66 {
67 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; 67 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
68 } 68 }
69 69
70 public void RegionLoaded(Scene scene) 70 public void RegionLoaded(Scene scene)
71 { 71 {
72 m_dialogModule = scene.RequestModuleInterface<IDialogModule>(); 72 m_dialogModule = scene.RequestModuleInterface<IDialogModule>();
73 } 73 }
74 74
75 public void Close() 75 public void Close()
76 { 76 {
77 RemoveRegion(m_scene); 77 RemoveRegion(m_scene);
78 } 78 }
79 79
80 public void SubscribeToClientEvents(IClientAPI client) 80 public void SubscribeToClientEvents(IClientAPI client)
81 { 81 {
82 client.OnObjectSaleInfo += ObjectSaleInfo; 82 client.OnObjectSaleInfo += ObjectSaleInfo;
@@ -89,18 +89,23 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
89 if (part == null) 89 if (part == null)
90 return; 90 return;
91 91
92 if (part.ParentGroup.IsDeleted) 92 SceneObjectGroup sog = part.ParentGroup;
93 if (sog == null || sog.IsDeleted)
93 return; 94 return;
94 95
95 if (part.OwnerID != client.AgentId && (!m_scene.Permissions.IsGod(client.AgentId))) 96 // Does the user have the power to put the object on sale?
97 if (!m_scene.Permissions.CanSellObject(client, sog, saleType))
98 {
99 client.SendAgentAlertMessage("You don't have permission to set object on sale", false);
96 return; 100 return;
101 }
97 102
98 part = part.ParentGroup.RootPart; 103 part = sog.RootPart;
99 104
100 part.ObjectSaleType = saleType; 105 part.ObjectSaleType = saleType;
101 part.SalePrice = salePrice; 106 part.SalePrice = salePrice;
102 107
103 part.ParentGroup.HasGroupChanged = true; 108 sog.HasGroupChanged = true;
104 109
105 part.SendPropertiesToClient(client); 110 part.SendPropertiesToClient(client);
106 } 111 }
@@ -113,11 +118,16 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
113 return false; 118 return false;
114 119
115 SceneObjectGroup group = part.ParentGroup; 120 SceneObjectGroup group = part.ParentGroup;
121 if(group == null || group.IsDeleted || group.inTransit)
122 return false;
123
124 // make sure we are not buying a child part
125 part = group.RootPart;
116 126
117 switch (saleType) 127 switch (saleType)
118 { 128 {
119 case 1: // Sell as original (in-place sale) 129 case 1: // Sell as original (in-place sale)
120 uint effectivePerms = group.GetEffectivePermissions(); 130 uint effectivePerms = group.EffectiveOwnerPerms;
121 131
122 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) 132 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
123 { 133 {
@@ -126,8 +136,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
126 return false; 136 return false;
127 } 137 }
128 138
129 group.SetOwnerId(remoteClient.AgentId); 139 group.SetOwner(remoteClient.AgentId, remoteClient.ActiveGroupId);
130 group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId);
131 140
132 if (m_scene.Permissions.PropagatePermissions()) 141 if (m_scene.Permissions.PropagatePermissions())
133 { 142 {
@@ -137,6 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
137 child.TriggerScriptChangedEvent(Changed.OWNER); 146 child.TriggerScriptChangedEvent(Changed.OWNER);
138 child.ApplyNextOwnerPermissions(); 147 child.ApplyNextOwnerPermissions();
139 } 148 }
149 group.InvalidateDeepEffectivePerms();
140 } 150 }
141 151
142 part.ObjectSaleType = 0; 152 part.ObjectSaleType = 0;
@@ -152,19 +162,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
152 break; 162 break;
153 163
154 case 2: // Sell a copy 164 case 2: // Sell a copy
155 Vector3 inventoryStoredPosition = new Vector3( 165 uint perms = group.EffectiveOwnerPerms;
156 Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6),
157 Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6),
158 group.AbsolutePosition.Z);
159
160 Vector3 originalPosition = group.AbsolutePosition;
161
162 group.AbsolutePosition = inventoryStoredPosition;
163
164 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(group);
165 group.AbsolutePosition = originalPosition;
166
167 uint perms = group.GetEffectivePermissions();
168 166
169 if ((perms & (uint)PermissionMask.Transfer) == 0) 167 if ((perms & (uint)PermissionMask.Transfer) == 0)
170 { 168 {
@@ -173,6 +171,15 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
173 return false; 171 return false;
174 } 172 }
175 173
174 if ((perms & (uint)PermissionMask.Copy) == 0)
175 {
176 if (m_dialogModule != null)
177 m_dialogModule.SendAlertToUser(remoteClient, "This sale has been blocked by the permissions system");
178 return false;
179 }
180
181 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(group);
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),
@@ -193,16 +200,21 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
193 item.AssetType = asset.Type; 200 item.AssetType = asset.Type;
194 item.InvType = (int)InventoryType.Object; 201 item.InvType = (int)InventoryType.Object;
195 item.Folder = categoryID; 202 item.Folder = categoryID;
203
204 perms = group.CurrentAndFoldedNextPermissions();
205 // apply parts inventory next perms
206 PermissionsUtil.ApplyNoModFoldedPermissions(perms, ref perms);
207 // change to next owner perms
208 perms &= part.NextOwnerMask;
209 // update folded
210 perms = PermissionsUtil.FixAndFoldPermissions(perms);
211
212 item.BasePermissions = perms;
213 item.CurrentPermissions = perms;
214 item.NextPermissions = part.NextOwnerMask & perms;
215 item.EveryOnePermissions = part.EveryoneMask & perms;
216 item.GroupPermissions = part.GroupMask & perms;
196 217
197 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
198
199 item.BasePermissions = perms & part.NextOwnerMask;
200 item.CurrentPermissions = perms & part.NextOwnerMask;
201 item.NextPermissions = part.NextOwnerMask;
202 item.EveryOnePermissions = part.EveryoneMask &
203 part.NextOwnerMask;
204 item.GroupPermissions = part.GroupMask &
205 part.NextOwnerMask;
206 item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 218 item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
207 item.CreationDate = Util.UnixTimeSinceEpoch(); 219 item.CreationDate = Util.UnixTimeSinceEpoch();
208 220
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index e77f0aa..3d786dd 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -53,30 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectCommandsModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectCommandsModule")]
54 public class ObjectCommandsModule : INonSharedRegionModule 54 public class ObjectCommandsModule : INonSharedRegionModule
55 { 55 {
56// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 57
58 private Scene m_scene; 58 private Scene m_scene;
59 private ICommandConsole m_console; 59 private ICommandConsole m_console;
60 60
61 public string Name { get { return "Object Commands Module"; } } 61 public string Name { get { return "Object Commands Module"; } }
62 62
63 public Type ReplaceableInterface { get { return null; } } 63 public Type ReplaceableInterface { get { return null; } }
64 64
65 public void Initialise(IConfigSource source) 65 public void Initialise(IConfigSource source)
66 { 66 {
67// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE"); 67// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE");
68 } 68 }
69 69
70 public void PostInitialise() 70 public void PostInitialise()
71 { 71 {
72// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE"); 72// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE");
73 } 73 }
74 74
75 public void Close() 75 public void Close()
76 { 76 {
77// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE"); 77// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE");
78 } 78 }
79 79
80 public void AddRegion(Scene scene) 80 public void AddRegion(Scene scene)
81 { 81 {
82// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); 82// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
@@ -123,8 +123,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
123 "Objects", 123 "Objects",
124 false, 124 false,
125 "delete object pos", 125 "delete object pos",
126 "delete object pos <start-coord> to <end-coord>", 126 "delete object pos <start x, start y , start z> <end x, end y, end z>",
127 "Delete scene objects within the given area.", 127 "Delete scene objects within the given volume.",
128 ConsoleUtil.CoordHelp, 128 ConsoleUtil.CoordHelp,
129 HandleDeleteObject); 129 HandleDeleteObject);
130 130
@@ -152,9 +152,18 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
152 m_console.Commands.AddCommand( 152 m_console.Commands.AddCommand(
153 "Objects", 153 "Objects",
154 false, 154 false,
155 "show object owner",
156 "show object owner [--full] <OwnerID>",
157 "Show details of scene objects with given owner.",
158 "The --full option will print out information on all the parts of the object.\n",
159 HandleShowObjectByOwnerID);
160
161 m_console.Commands.AddCommand(
162 "Objects",
163 false,
155 "show object pos", 164 "show object pos",
156 "show object pos [--full] <start-coord> to <end-coord>", 165 "show object pos [--full] <start x, start y , start z> <end x, end y, end z>",
157 "Show details of scene objects within the given area.", 166 "Show details of scene objects within give volume",
158 "The --full option will print out information on all the parts of the object.\n" 167 "The --full option will print out information on all the parts of the object.\n"
159 + "For yet more detailed part information, use the \"show part\" commands.\n" 168 + "For yet more detailed part information, use the \"show part\" commands.\n"
160 + ConsoleUtil.CoordHelp, 169 + ConsoleUtil.CoordHelp,
@@ -180,8 +189,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
180 "Objects", 189 "Objects",
181 false, 190 false,
182 "show part pos", 191 "show part pos",
183 "show part pos <start-coord> to <end-coord>", 192 "show part pos <start x, start y , start z> <end x, end y, end z>",
184 "Show details of scene object parts within the given area.", 193 "Show details of scene object parts within the given volume.",
185 ConsoleUtil.CoordHelp, 194 ConsoleUtil.CoordHelp,
186 HandleShowPartByPos); 195 HandleShowPartByPos);
187 196
@@ -325,6 +334,32 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
325 OutputSogsToConsole(searchPredicate, showFull); 334 OutputSogsToConsole(searchPredicate, showFull);
326 } 335 }
327 336
337 private void HandleShowObjectByOwnerID(string module, string[] cmdparams)
338 {
339 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
340 return;
341
342 bool showFull = false;
343 OptionSet options = new OptionSet().Add("full", v => showFull = v != null);
344
345 List<string> mainParams = options.Parse(cmdparams);
346
347 if (mainParams.Count < 4)
348 {
349 m_console.OutputFormat("Usage: show object owner <OwnerID>");
350 return;
351 }
352
353 UUID ownerID;
354 if (!ConsoleUtil.TryParseConsoleUuid(m_console, mainParams[3], out ownerID))
355 return;
356
357 Predicate<SceneObjectGroup> searchPredicate
358 = so => so.OwnerID == ownerID && !so.IsAttachment;
359
360 OutputSogsToConsole(searchPredicate, showFull);
361 }
362
328 private void HandleShowObjectByPos(string module, string[] cmdparams) 363 private void HandleShowObjectByPos(string module, string[] cmdparams)
329 { 364 {
330 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 365 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
@@ -504,13 +539,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
504 539
505 if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) 540 if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName))
506 return; 541 return;
507 542
508 using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) 543 using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8))
509 { 544 {
510 xtw.Formatting = Formatting.Indented; 545 xtw.Formatting = Formatting.Indented;
511 SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); 546 SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true);
512 } 547 }
513 548
514 m_console.OutputFormat("Object dumped to file {0}", fileName); 549 m_console.OutputFormat("Object dumped to file {0}", fileName);
515 } 550 }
516 551
@@ -590,7 +625,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
590 cdl.AddRow("FlexiSoftness", s.FlexiSoftness); 625 cdl.AddRow("FlexiSoftness", s.FlexiSoftness);
591 cdl.AddRow("HollowShape", s.HollowShape); 626 cdl.AddRow("HollowShape", s.HollowShape);
592 cdl.AddRow( 627 cdl.AddRow(
593 "LightColor", 628 "LightColor",
594 string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA)); 629 string.Format("<{0},{1},{2},{3}>", s.LightColorR, s.LightColorB, s.LightColorG, s.LightColorA));
595 cdl.AddRow("LightCutoff", s.LightCutoff); 630 cdl.AddRow("LightCutoff", s.LightCutoff);
596 cdl.AddRow("LightEntry", s.LightEntry); 631 cdl.AddRow("LightEntry", s.LightEntry);
@@ -624,7 +659,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
624 cdl.AddRow("Rotation (World)", sop.GetWorldRotation()); 659 cdl.AddRow("Rotation (World)", sop.GetWorldRotation());
625 cdl.AddRow("Scale", s.Scale); 660 cdl.AddRow("Scale", s.Scale);
626 cdl.AddRow( 661 cdl.AddRow(
627 "SculptData", 662 "SculptData",
628 string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a")); 663 string.Format("{0} bytes", s.SculptData != null ? s.SculptData.Length.ToString() : "n/a"));
629 cdl.AddRow("SculptEntry", s.SculptEntry); 664 cdl.AddRow("SculptEntry", s.SculptEntry);
630 cdl.AddRow("SculptTexture", s.SculptTexture); 665 cdl.AddRow("SculptTexture", s.SculptTexture);
@@ -633,7 +668,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
633 668
634 // TODO, need to display more information about textures but in a compact format 669 // TODO, need to display more information about textures but in a compact format
635 // to stop output becoming huge. 670 // to stop output becoming huge.
636 for (int i = 0; i < sop.GetNumberOfSides(); i++) 671 for (int i = 0; i < sop.GetNumberOfSides(); i++)
637 { 672 {
638 Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i]; 673 Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i];
639 674
@@ -730,12 +765,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
730 if (g.OwnerID == match && !g.IsAttachment) 765 if (g.OwnerID == match && !g.IsAttachment)
731 deletes.Add(g); 766 deletes.Add(g);
732 }); 767 });
733 768
734 // if (deletes.Count == 0) 769 // if (deletes.Count == 0)
735 // m_console.OutputFormat("No objects were found with owner {0}", match); 770 // m_console.OutputFormat("No objects were found with owner {0}", match);
736 771
737 break; 772 break;
738 773
739 case "creator": 774 case "creator":
740 if (!UUID.TryParse(o, out match)) 775 if (!UUID.TryParse(o, out match))
741 return; 776 return;
@@ -747,12 +782,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
747 if (g.RootPart.CreatorID == match && !g.IsAttachment) 782 if (g.RootPart.CreatorID == match && !g.IsAttachment)
748 deletes.Add(g); 783 deletes.Add(g);
749 }); 784 });
750 785
751 // if (deletes.Count == 0) 786 // if (deletes.Count == 0)
752 // m_console.OutputFormat("No objects were found with creator {0}", match); 787 // m_console.OutputFormat("No objects were found with creator {0}", match);
753 788
754 break; 789 break;
755 790
756 case "id": 791 case "id":
757 UUID uuid; 792 UUID uuid;
758 uint localId; 793 uint localId;
@@ -768,18 +803,21 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
768 else 803 else
769 so = m_scene.GetSceneObjectGroup(localId); 804 so = m_scene.GetSceneObjectGroup(localId);
770 805
771 if (!so.IsAttachment) 806 if (so!= null)
772 deletes.Add(so); 807 {
773 808 deletes.Add(so);
774 // if (deletes.Count == 0) 809 if(so.IsAttachment)
775 // m_console.OutputFormat("No objects were found with uuid {0}", match); 810 {
776 811 requireConfirmation = true;
812 m_console.OutputFormat("Warning: object with uuid {0} is a attachment", uuid);
813 }
814 }
777 break; 815 break;
778 816
779 case "name": 817 case "name":
780 deletes = GetDeleteCandidatesByName(module, cmd); 818 deletes = GetDeleteCandidatesByName(module, cmd);
781 break; 819 break;
782 820
783 case "outside": 821 case "outside":
784 deletes = new List<SceneObjectGroup>(); 822 deletes = new List<SceneObjectGroup>();
785 823
@@ -787,7 +825,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
787 { 825 {
788 SceneObjectPart rootPart = g.RootPart; 826 SceneObjectPart rootPart = g.RootPart;
789 bool delete = false; 827 bool delete = false;
790 828
791 if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) 829 if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0)
792 { 830 {
793 delete = true; 831 delete = true;
@@ -796,18 +834,18 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
796 { 834 {
797 ILandObject parcel 835 ILandObject parcel
798 = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y); 836 = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y);
799 837
800 if (parcel == null || parcel.LandData.Name == "NO LAND") 838 if (parcel == null || parcel.LandData.Name == "NO LAND")
801 delete = true; 839 delete = true;
802 } 840 }
803 841
804 if (delete && !g.IsAttachment && !deletes.Contains(g)) 842 if (delete && !g.IsAttachment && !deletes.Contains(g))
805 deletes.Add(g); 843 deletes.Add(g);
806 }); 844 });
807 845
808 if (deletes.Count == 0) 846 if (deletes.Count == 0)
809 m_console.OutputFormat("No objects were found outside region bounds"); 847 m_console.OutputFormat("No objects were found outside region bounds");
810 848
811 break; 849 break;
812 850
813 case "pos": 851 case "pos":
@@ -829,7 +867,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
829 "Are you sure that you want to delete {0} objects from {1}", 867 "Are you sure that you want to delete {0} objects from {1}",
830 deletes.Count, m_scene.RegionInfo.RegionName), 868 deletes.Count, m_scene.RegionInfo.RegionName),
831 "y/N"); 869 "y/N");
832 870
833 if (response.ToLower() != "y") 871 if (response.ToLower() != "y")
834 { 872 {
835 MainConsole.Instance.OutputFormat( 873 MainConsole.Instance.OutputFormat(
@@ -869,11 +907,11 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
869 if (useRegex) 907 if (useRegex)
870 { 908 {
871 Regex nameRegex = new Regex(name); 909 Regex nameRegex = new Regex(name);
872 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; 910 searchAction = so => { if (nameRegex.IsMatch(so.Name)) {if(!so.IsAttachment) sceneObjects.Add(so);}};
873 } 911 }
874 else 912 else
875 { 913 {
876 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; 914 searchAction = so => { if (so.Name == name) {if(!so.IsAttachment) sceneObjects.Add(so);}};
877 } 915 }
878 916
879 m_scene.ForEachSOG(searchAction); 917 m_scene.ForEachSOG(searchAction);
@@ -916,11 +954,11 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
916 { 954 {
917 m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector); 955 m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector);
918 endVector = Vector3.Zero; 956 endVector = Vector3.Zero;
919 957
920 return false; 958 return false;
921 } 959 }
922 960
923 string rawConsoleEndVector = rawComponents.Skip(2).Take(1).Single(); 961 string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
924 962
925 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) 963 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
926 { 964 {
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 780ec69..45c1c56 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -43,12 +43,13 @@ 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
51 protected Scene m_scene; 51 protected Scene m_scene;
52 protected ScenePermissions scenePermissions;
52 protected bool m_Enabled; 53 protected bool m_Enabled;
53 54
54 private InventoryFolderImpl m_libraryRootFolder; 55 private InventoryFolderImpl m_libraryRootFolder;
@@ -69,15 +70,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
69 } 70 }
70 71
71 #region Constants 72 #region Constants
72 // These are here for testing. They will be taken out
73
74 //private uint PERM_ALL = (uint)2147483647;
75 private uint PERM_COPY = (uint)32768;
76 //private uint PERM_MODIFY = (uint)16384;
77 private uint PERM_MOVE = (uint)524288;
78 private uint PERM_TRANS = (uint)8192;
79 private uint PERM_LOCKED = (uint)540672;
80
81 /// <value> 73 /// <value>
82 /// Different user set names that come in from the configuration file. 74 /// Different user set names that come in from the configuration file.
83 /// </value> 75 /// </value>
@@ -96,12 +88,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
96 private bool m_bypassPermissionsValue = true; 88 private bool m_bypassPermissionsValue = true;
97 private bool m_propagatePermissions = false; 89 private bool m_propagatePermissions = false;
98 private bool m_debugPermissions = false; 90 private bool m_debugPermissions = false;
99 private bool m_allowGridGods = false; 91 private bool m_allowGridAdmins = false;
100 private bool m_RegionOwnerIsGod = false; 92 private bool m_RegionOwnerIsAdmin = false;
101 private bool m_RegionManagerIsGod = false; 93 private bool m_RegionManagerIsAdmin = false;
102 private bool m_ParcelOwnerIsGod = false; 94 private bool m_forceGridAdminsOnly;
103 95 private bool m_forceAdminModeAlwaysOn;
104 private bool m_SimpleBuildPermissions = false; 96 private bool m_allowAdminActionsWithoutGodMode;
105 97
106 /// <value> 98 /// <value>
107 /// The set of users that are allowed to create scripts. This is only active if permissions are not being 99 /// The set of users that are allowed to create scripts. This is only active if permissions are not being
@@ -110,17 +102,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions
110 private UserSet m_allowedScriptCreators = UserSet.All; 102 private UserSet m_allowedScriptCreators = UserSet.All;
111 103
112 /// <value> 104 /// <value>
113 /// The set of users that are allowed to edit (save) scripts. This is only active if 105 /// The set of users that are allowed to edit (save) scripts. This is only active if
114 /// permissions are not being bypassed. This overrides normal permissions.- 106 /// permissions are not being bypassed. This overrides normal permissions.-
115 /// </value> 107 /// </value>
116 private UserSet m_allowedScriptEditors = UserSet.All; 108 private UserSet m_allowedScriptEditors = UserSet.All;
117 109
118 private Dictionary<string, bool> GrantLSL = new Dictionary<string, bool>(); 110 private Dictionary<string, bool> GrantLSL = new Dictionary<string, bool>();
119 private Dictionary<string, bool> GrantCS = new Dictionary<string, bool>(); 111 private Dictionary<string, bool> GrantCS = new Dictionary<string, bool>();
120 private Dictionary<string, bool> GrantVB = new Dictionary<string, bool>(); 112 private Dictionary<string, bool> GrantVB = new Dictionary<string, bool>();
121 private Dictionary<string, bool> GrantJS = new Dictionary<string, bool>(); 113 private Dictionary<string, bool> GrantJS = new Dictionary<string, bool>();
122 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>(); 114 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>();
123 115
124 private IFriendsModule m_friendsModule; 116 private IFriendsModule m_friendsModule;
125 private IFriendsModule FriendsModule 117 private IFriendsModule FriendsModule
126 { 118 {
@@ -168,21 +160,25 @@ namespace OpenSim.Region.CoreModules.World.Permissions
168 160
169 m_Enabled = true; 161 m_Enabled = true;
170 162
171 m_allowGridGods = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", 163 string[] sections = new string[] { "Startup", "Permissions" };
172 new string[] { "Startup", "Permissions" }, false); 164
173 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions", 165 m_allowGridAdmins = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", sections, false);
174 new string[] { "Startup", "Permissions" }, true); 166 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions", sections, true);
175 m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions", 167 m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions", sections, true);
176 new string[] { "Startup", "Permissions" }, true); 168
177 m_RegionOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god", 169 m_forceGridAdminsOnly = Util.GetConfigVarFromSections<bool>(config, "force_grid_gods_only", sections, false);
178 new string[] { "Startup", "Permissions" }, true); 170 if(!m_forceGridAdminsOnly)
179 m_RegionManagerIsGod = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god", 171 {
180 new string[] { "Startup", "Permissions" }, false); 172 m_RegionOwnerIsAdmin = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god",sections, true);
181 m_ParcelOwnerIsGod = Util.GetConfigVarFromSections<bool>(config, "parcel_owner_is_god", 173 m_RegionManagerIsAdmin = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god",sections, false);
182 new string[] { "Startup", "Permissions" }, true); 174 }
183 175 else
184 m_SimpleBuildPermissions = Util.GetConfigVarFromSections<bool>(config, "simple_build_permissions", 176 m_allowGridAdmins = true;
185 new string[] { "Startup", "Permissions" }, false); 177
178 m_forceAdminModeAlwaysOn = Util.GetConfigVarFromSections<bool>(config, "automatic_gods", sections, false);
179 m_allowAdminActionsWithoutGodMode = Util.GetConfigVarFromSections<bool>(config, "implicit_gods", sections, false);
180 if(m_allowAdminActionsWithoutGodMode)
181 m_forceAdminModeAlwaysOn = false;
186 182
187 m_allowedScriptCreators 183 m_allowedScriptCreators
188 = ParseUserSetConfigSetting(config, "allowed_script_creators", m_allowedScriptCreators); 184 = ParseUserSetConfigSetting(config, "allowed_script_creators", m_allowedScriptCreators);
@@ -206,7 +202,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
206 } 202 }
207 203
208 grant = Util.GetConfigVarFromSections<string>(config, "GrantCS", 204 grant = Util.GetConfigVarFromSections<string>(config, "GrantCS",
209 new string[] { "Startup", "Permissions" }, string.Empty); 205 new string[] { "Startup", "Permissions" }, string.Empty);
210 if (grant.Length > 0) 206 if (grant.Length > 0)
211 { 207 {
212 foreach (string uuidl in grant.Split(',')) 208 foreach (string uuidl in grant.Split(','))
@@ -258,61 +254,79 @@ namespace OpenSim.Region.CoreModules.World.Permissions
258 m_scene = scene; 254 m_scene = scene;
259 255
260 scene.RegisterModuleInterface<IPermissionsModule>(this); 256 scene.RegisterModuleInterface<IPermissionsModule>(this);
257 scenePermissions = m_scene.Permissions;
261 258
262 //Register functions with Scene External Checks! 259 //Register functions with Scene External Checks!
263 m_scene.Permissions.OnBypassPermissions += BypassPermissions; 260 scenePermissions.OnBypassPermissions += BypassPermissions;
264 m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; 261 scenePermissions.OnSetBypassPermissions += SetBypassPermissions;
265 m_scene.Permissions.OnPropagatePermissions += PropagatePermissions; 262 scenePermissions.OnPropagatePermissions += PropagatePermissions;
266 m_scene.Permissions.OnGenerateClientFlags += GenerateClientFlags; 263
267 m_scene.Permissions.OnAbandonParcel += CanAbandonParcel; 264 scenePermissions.OnIsGridGod += IsGridAdministrator;
268 m_scene.Permissions.OnReclaimParcel += CanReclaimParcel; 265 scenePermissions.OnIsAdministrator += IsAdministrator;
269 m_scene.Permissions.OnDeedParcel += CanDeedParcel; 266 scenePermissions.OnIsEstateManager += IsEstateManager;
270 m_scene.Permissions.OnDeedObject += CanDeedObject; 267
271 m_scene.Permissions.OnIsGod += IsGod; 268 scenePermissions.OnGenerateClientFlags += GenerateClientFlags;
272 m_scene.Permissions.OnIsGridGod += IsGridGod; 269
273 m_scene.Permissions.OnIsAdministrator += IsAdministrator; 270 scenePermissions.OnIssueEstateCommand += CanIssueEstateCommand;
274 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; 271 scenePermissions.OnRunConsoleCommand += CanRunConsoleCommand;
275 m_scene.Permissions.OnDeleteObject += CanDeleteObject; 272
276 m_scene.Permissions.OnEditObject += CanEditObject; 273 scenePermissions.OnTeleport += CanTeleport;
277 m_scene.Permissions.OnEditParcelProperties += CanEditParcelProperties; 274
278 m_scene.Permissions.OnInstantMessage += CanInstantMessage; 275 scenePermissions.OnInstantMessage += CanInstantMessage;
279 m_scene.Permissions.OnInventoryTransfer += CanInventoryTransfer; 276
280 m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; 277 scenePermissions.OnAbandonParcel += CanAbandonParcel;
281 m_scene.Permissions.OnMoveObject += CanMoveObject; 278 scenePermissions.OnReclaimParcel += CanReclaimParcel;
282 m_scene.Permissions.OnObjectEntry += CanObjectEntry; 279 scenePermissions.OnDeedParcel += CanDeedParcel;
283 m_scene.Permissions.OnReturnObjects += CanReturnObjects; 280 scenePermissions.OnSellParcel += CanSellParcel;
284 m_scene.Permissions.OnRezObject += CanRezObject; 281 scenePermissions.OnEditParcelProperties += CanEditParcelProperties;
285 m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand; 282 scenePermissions.OnTerraformLand += CanTerraformLand;
286 m_scene.Permissions.OnRunScript += CanRunScript; 283 scenePermissions.OnBuyLand += CanBuyLand;
287 m_scene.Permissions.OnCompileScript += CanCompileScript; 284
288 m_scene.Permissions.OnSellParcel += CanSellParcel; 285 scenePermissions.OnReturnObjects += CanReturnObjects;
289 m_scene.Permissions.OnTakeObject += CanTakeObject; 286
290 m_scene.Permissions.OnTakeCopyObject += CanTakeCopyObject; 287 scenePermissions.OnRezObject += CanRezObject;
291 m_scene.Permissions.OnTerraformLand += CanTerraformLand; 288 scenePermissions.OnObjectEntry += CanObjectEntry;
292 m_scene.Permissions.OnLinkObject += CanLinkObject; 289 scenePermissions.OnObjectEnterWithScripts += OnObjectEnterWithScripts;
293 m_scene.Permissions.OnDelinkObject += CanDelinkObject; 290
294 m_scene.Permissions.OnBuyLand += CanBuyLand; 291 scenePermissions.OnDuplicateObject += CanDuplicateObject;
295 292 scenePermissions.OnDeleteObjectByIDs += CanDeleteObjectByIDs;
296 m_scene.Permissions.OnViewNotecard += CanViewNotecard; 293 scenePermissions.OnDeleteObject += CanDeleteObject;
297 m_scene.Permissions.OnViewScript += CanViewScript; 294 scenePermissions.OnEditObjectByIDs += CanEditObjectByIDs;
298 m_scene.Permissions.OnEditNotecard += CanEditNotecard; 295 scenePermissions.OnEditObject += CanEditObject;
299 m_scene.Permissions.OnEditScript += CanEditScript; 296 scenePermissions.OnEditObjectPerms += CanEditObjectPerms;
300 297 scenePermissions.OnInventoryTransfer += CanInventoryTransfer;
301 m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory; 298 scenePermissions.OnMoveObject += CanMoveObject;
302 m_scene.Permissions.OnEditObjectInventory += CanEditObjectInventory; 299 scenePermissions.OnTakeObject += CanTakeObject;
303 m_scene.Permissions.OnCopyObjectInventory += CanCopyObjectInventory; 300 scenePermissions.OnTakeCopyObject += CanTakeCopyObject;
304 m_scene.Permissions.OnDeleteObjectInventory += CanDeleteObjectInventory; 301 scenePermissions.OnLinkObject += CanLinkObject;
305 m_scene.Permissions.OnResetScript += CanResetScript; 302 scenePermissions.OnDelinkObject += CanDelinkObject;
303 scenePermissions.OnDeedObject += CanDeedObject;
304 scenePermissions.OnSellGroupObject += CanSellGroupObject;
305 scenePermissions.OnSellObjectByUserID += CanSellObjectByUserID;
306 scenePermissions.OnSellObject += CanSellObject;
306 307
307 m_scene.Permissions.OnCreateUserInventory += CanCreateUserInventory; 308 scenePermissions.OnCreateObjectInventory += CanCreateObjectInventory;
308 m_scene.Permissions.OnCopyUserInventory += CanCopyUserInventory; 309 scenePermissions.OnEditObjectInventory += CanEditObjectInventory;
309 m_scene.Permissions.OnEditUserInventory += CanEditUserInventory; 310 scenePermissions.OnCopyObjectInventory += CanCopyObjectInventory;
310 m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; 311 scenePermissions.OnDeleteObjectInventory += CanDeleteObjectInventory;
312 scenePermissions.OnDoObjectInvToObjectInv += CanDoObjectInvToObjectInv;
313 scenePermissions.OnDropInObjectInv += CanDropInObjectInv;
314
315 scenePermissions.OnViewNotecard += CanViewNotecard;
316 scenePermissions.OnViewScript += CanViewScript;
317 scenePermissions.OnEditNotecard += CanEditNotecard;
318 scenePermissions.OnEditScript += CanEditScript;
319 scenePermissions.OnResetScript += CanResetScript;
320 scenePermissions.OnRunScript += CanRunScript;
321 scenePermissions.OnCompileScript += CanCompileScript;
311 322
312 m_scene.Permissions.OnTeleport += CanTeleport; 323 scenePermissions.OnCreateUserInventory += CanCreateUserInventory;
313 324 scenePermissions.OnCopyUserInventory += CanCopyUserInventory;
314 m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia; 325 scenePermissions.OnEditUserInventory += CanEditUserInventory;
315 m_scene.Permissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia; 326 scenePermissions.OnDeleteUserInventory += CanDeleteUserInventory;
327
328 scenePermissions.OnControlPrimMedia += CanControlPrimMedia;
329 scenePermissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia;
316 330
317 m_scene.AddCommand("Users", this, "bypass permissions", 331 m_scene.AddCommand("Users", this, "bypass permissions",
318 "bypass permissions <true / false>", 332 "bypass permissions <true / false>",
@@ -327,8 +341,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
327 m_scene.AddCommand("Debug", this, "debug permissions", 341 m_scene.AddCommand("Debug", this, "debug permissions",
328 "debug permissions <true / false>", 342 "debug permissions <true / false>",
329 "Turn on permissions debugging", 343 "Turn on permissions debugging",
330 HandleDebugPermissions); 344 HandleDebugPermissions);
331 345
332 } 346 }
333 347
334 public void RegionLoaded(Scene scene) 348 public void RegionLoaded(Scene scene)
@@ -341,6 +355,79 @@ namespace OpenSim.Region.CoreModules.World.Permissions
341 return; 355 return;
342 356
343 m_scene.UnregisterModuleInterface<IPermissionsModule>(this); 357 m_scene.UnregisterModuleInterface<IPermissionsModule>(this);
358
359 scenePermissions.OnBypassPermissions -= BypassPermissions;
360 scenePermissions.OnSetBypassPermissions -= SetBypassPermissions;
361 scenePermissions.OnPropagatePermissions -= PropagatePermissions;
362
363 scenePermissions.OnIsGridGod -= IsGridAdministrator;
364 scenePermissions.OnIsAdministrator -= IsAdministrator;
365 scenePermissions.OnIsEstateManager -= IsEstateManager;
366
367 scenePermissions.OnGenerateClientFlags -= GenerateClientFlags;
368
369 scenePermissions.OnIssueEstateCommand -= CanIssueEstateCommand;
370 scenePermissions.OnRunConsoleCommand -= CanRunConsoleCommand;
371
372 scenePermissions.OnTeleport -= CanTeleport;
373
374 scenePermissions.OnInstantMessage -= CanInstantMessage;
375
376 scenePermissions.OnAbandonParcel -= CanAbandonParcel;
377 scenePermissions.OnReclaimParcel -= CanReclaimParcel;
378 scenePermissions.OnDeedParcel -= CanDeedParcel;
379 scenePermissions.OnSellParcel -= CanSellParcel;
380 scenePermissions.OnEditParcelProperties -= CanEditParcelProperties;
381 scenePermissions.OnTerraformLand -= CanTerraformLand;
382 scenePermissions.OnBuyLand -= CanBuyLand;
383
384 scenePermissions.OnRezObject -= CanRezObject;
385 scenePermissions.OnObjectEntry -= CanObjectEntry;
386 scenePermissions.OnObjectEnterWithScripts -= OnObjectEnterWithScripts;
387
388 scenePermissions.OnReturnObjects -= CanReturnObjects;
389
390 scenePermissions.OnDuplicateObject -= CanDuplicateObject;
391 scenePermissions.OnDeleteObjectByIDs -= CanDeleteObjectByIDs;
392 scenePermissions.OnDeleteObject -= CanDeleteObject;
393 scenePermissions.OnEditObjectByIDs -= CanEditObjectByIDs;
394 scenePermissions.OnEditObject -= CanEditObject;
395 scenePermissions.OnEditObjectPerms -= CanEditObjectPerms;
396 scenePermissions.OnInventoryTransfer -= CanInventoryTransfer;
397 scenePermissions.OnMoveObject -= CanMoveObject;
398 scenePermissions.OnTakeObject -= CanTakeObject;
399 scenePermissions.OnTakeCopyObject -= CanTakeCopyObject;
400 scenePermissions.OnLinkObject -= CanLinkObject;
401 scenePermissions.OnDelinkObject -= CanDelinkObject;
402 scenePermissions.OnDeedObject -= CanDeedObject;
403
404 scenePermissions.OnSellGroupObject -= CanSellGroupObject;
405 scenePermissions.OnSellObjectByUserID -= CanSellObjectByUserID;
406 scenePermissions.OnSellObject -= CanSellObject;
407
408 scenePermissions.OnCreateObjectInventory -= CanCreateObjectInventory;
409 scenePermissions.OnEditObjectInventory -= CanEditObjectInventory;
410 scenePermissions.OnCopyObjectInventory -= CanCopyObjectInventory;
411 scenePermissions.OnDeleteObjectInventory -= CanDeleteObjectInventory;
412 scenePermissions.OnDoObjectInvToObjectInv -= CanDoObjectInvToObjectInv;
413 scenePermissions.OnDropInObjectInv -= CanDropInObjectInv;
414
415 scenePermissions.OnViewNotecard -= CanViewNotecard;
416 scenePermissions.OnViewScript -= CanViewScript;
417 scenePermissions.OnEditNotecard -= CanEditNotecard;
418 scenePermissions.OnEditScript -= CanEditScript;
419 scenePermissions.OnResetScript -= CanResetScript;
420 scenePermissions.OnRunScript -= CanRunScript;
421 scenePermissions.OnCompileScript -= CanCompileScript;
422
423 scenePermissions.OnCreateUserInventory -= CanCreateUserInventory;
424 scenePermissions.OnCopyUserInventory -= CanCopyUserInventory;
425 scenePermissions.OnEditUserInventory -= CanEditUserInventory;
426 scenePermissions.OnDeleteUserInventory -= CanDeleteUserInventory;
427
428 scenePermissions.OnControlPrimMedia -= CanControlPrimMedia;
429 scenePermissions.OnInteractWithPrimMedia -= CanInteractWithPrimMedia;
430
344 } 431 }
345 432
346 public void Close() 433 public void Close()
@@ -349,7 +436,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
349 436
350 public string Name 437 public string Name
351 { 438 {
352 get { return "PermissionsModule"; } 439 get { return "DefaultPermissionsModule"; }
353 } 440 }
354 441
355 public Type ReplaceableInterface 442 public Type ReplaceableInterface
@@ -439,7 +526,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
439 { 526 {
440 m_scene.EventManager.TriggerPermissionError(user, reason); 527 m_scene.EventManager.TriggerPermissionError(user, reason);
441 } 528 }
442 529
443 protected void DebugPermissionInformation(string permissionCalled) 530 protected void DebugPermissionInformation(string permissionCalled)
444 { 531 {
445 if (m_debugPermissions) 532 if (m_debugPermissions)
@@ -469,7 +556,37 @@ namespace OpenSim.Region.CoreModules.World.Permissions
469 556
470 return false; 557 return false;
471 } 558 }
472 559
560 protected bool GroupMemberPowers(UUID groupID, UUID userID, ref ulong powers)
561 {
562 powers = 0;
563 if (null == GroupsModule)
564 return false;
565
566 GroupMembershipData gmd = GroupsModule.GetMembershipData(groupID, userID);
567
568 if (gmd != null)
569 {
570 powers = gmd.GroupPowers;
571 return true;
572 }
573 return false;
574 }
575
576 protected bool GroupMemberPowers(UUID groupID, ScenePresence sp, ref ulong powers)
577 {
578 powers = 0;
579 IClientAPI client = sp.ControllingClient;
580 if (client == null)
581 return false;
582
583 if(!client.IsGroupMember(groupID))
584 return false;
585
586 powers = client.GetGroupPowers(groupID);
587 return true;
588 }
589
473 /// <summary> 590 /// <summary>
474 /// Parse a user set configuration setting 591 /// Parse a user set configuration setting
475 /// </summary> 592 /// </summary>
@@ -481,28 +598,28 @@ namespace OpenSim.Region.CoreModules.World.Permissions
481 { 598 {
482 UserSet userSet = defaultValue; 599 UserSet userSet = defaultValue;
483 600
484 string rawSetting = Util.GetConfigVarFromSections<string>(config, settingName, 601 string rawSetting = Util.GetConfigVarFromSections<string>(config, settingName,
485 new string[] {"Startup", "Permissions"}, defaultValue.ToString()); 602 new string[] {"Startup", "Permissions"}, defaultValue.ToString());
486 603
487 // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term 604 // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term
488 // this should disappear. 605 // this should disappear.
489 if ("gods" == rawSetting.ToLower()) 606 if ("gods" == rawSetting.ToLower())
490 rawSetting = UserSet.Administrators.ToString(); 607 rawSetting = UserSet.Administrators.ToString();
491 608
492 // Doing it this was so that we can do a case insensitive conversion 609 // Doing it this was so that we can do a case insensitive conversion
493 try 610 try
494 { 611 {
495 userSet = (UserSet)Enum.Parse(typeof(UserSet), rawSetting, true); 612 userSet = (UserSet)Enum.Parse(typeof(UserSet), rawSetting, true);
496 } 613 }
497 catch 614 catch
498 { 615 {
499 m_log.ErrorFormat( 616 m_log.ErrorFormat(
500 "[PERMISSIONS]: {0} is not a valid {1} value, setting to {2}", 617 "[PERMISSIONS]: {0} is not a valid {1} value, setting to {2}",
501 rawSetting, settingName, userSet); 618 rawSetting, settingName, userSet);
502 } 619 }
503 620
504 m_log.DebugFormat("[PERMISSIONS]: {0} {1}", settingName, userSet); 621 m_log.DebugFormat("[PERMISSIONS]: {0} {1}", settingName, userSet);
505 622
506 return userSet; 623 return userSet;
507 } 624 }
508 625
@@ -516,13 +633,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions
516 if (user == UUID.Zero) 633 if (user == UUID.Zero)
517 return false; 634 return false;
518 635
519 if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod) 636 if (m_RegionOwnerIsAdmin && m_scene.RegionInfo.EstateSettings.EstateOwner == user)
520 return true; 637 return true;
521 638
522 if (IsEstateManager(user) && m_RegionManagerIsGod) 639 if (m_RegionManagerIsAdmin && IsEstateManager(user))
523 return true; 640 return true;
524 641
525 if (IsGridGod(user, null)) 642 if (IsGridAdministrator(user))
526 return true; 643 return true;
527 644
528 return false; 645 return false;
@@ -534,18 +651,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
534 /// <param name="user">The user</param> 651 /// <param name="user">The user</param>
535 /// <param name="scene">Unused, can be null</param> 652 /// <param name="scene">Unused, can be null</param>
536 /// <returns></returns> 653 /// <returns></returns>
537 protected bool IsGridGod(UUID user, Scene scene) 654 protected bool IsGridAdministrator(UUID user)
538 { 655 {
539 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 656 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
540 if (m_bypassPermissions) return m_bypassPermissionsValue; 657 if (m_bypassPermissions) return m_bypassPermissionsValue;
541 658
542 if (user == UUID.Zero) return false; 659 if (user == UUID.Zero)
660 return false;
543 661
544 if (m_allowGridGods) 662 if (m_allowGridAdmins)
545 { 663 {
546 ScenePresence sp = m_scene.GetScenePresence(user); 664 ScenePresence sp = m_scene.GetScenePresence(user);
547 if (sp != null) 665 if (sp != null)
548 return (sp.UserLevel >= 200); 666 return (sp.GodController.UserLevel >= 200);
549 667
550 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user); 668 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user);
551 if (account != null) 669 if (account != null)
@@ -556,11 +674,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
556 } 674 }
557 675
558 protected bool IsFriendWithPerms(UUID user, UUID objectOwner) 676 protected bool IsFriendWithPerms(UUID user, UUID objectOwner)
559 { 677 {
560 if (user == UUID.Zero) 678 if (FriendsModule == null)
561 return false; 679 return false;
562 680
563 if (FriendsModule == null) 681 if (user == UUID.Zero)
564 return false; 682 return false;
565 683
566 int friendPerms = FriendsModule.GetRightsGrantedByFriend(user, objectOwner); 684 int friendPerms = FriendsModule.GetRightsGrantedByFriend(user, objectOwner);
@@ -570,7 +688,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
570 protected bool IsEstateManager(UUID user) 688 protected bool IsEstateManager(UUID user)
571 { 689 {
572 if (user == UUID.Zero) return false; 690 if (user == UUID.Zero) return false;
573 691
574 return m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(user); 692 return m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(user);
575 } 693 }
576 694
@@ -596,75 +714,178 @@ namespace OpenSim.Region.CoreModules.World.Permissions
596 714
597 #region Object Permissions 715 #region Object Permissions
598 716
599 public uint GenerateClientFlags(UUID user, UUID objID) 717 const uint DEFAULT_FLAGS = (uint)(
600 { 718 PrimFlags.ObjectCopy | // Tells client you can copy the object
601 // Here's the way this works, 719 PrimFlags.ObjectModify | // tells client you can modify the object
602 // ObjectFlags and Permission flags are two different enumerations 720 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
603 // ObjectFlags, however, tells the client to change what it will allow the user to do. 721 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
604 // So, that means that all of the permissions type ObjectFlags are /temporary/ and only 722 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
605 // supposed to be set when customizing the objectflags for the client. 723 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
724 PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object
725 );
726
727 const uint NOT_DEFAULT_FLAGS = (uint)~(
728 PrimFlags.ObjectCopy | // Tells client you can copy the object
729 PrimFlags.ObjectModify | // tells client you can modify the object
730 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
731 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
732 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
733 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
734 PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object
735 );
736
737 const uint EXTRAOWNERMASK = (uint)(
738 PrimFlags.ObjectYouOwner |
739 PrimFlags.ObjectAnyOwner
740 );
741
742 const uint EXTRAGODMASK = (uint)(
743 PrimFlags.ObjectYouOwner |
744 PrimFlags.ObjectAnyOwner |
745 PrimFlags.ObjectOwnerModify |
746 PrimFlags.ObjectModify |
747 PrimFlags.ObjectMove
748 );
749
750 const uint GOD_FLAGS = (uint)(
751 PrimFlags.ObjectCopy | // Tells client you can copy the object
752 PrimFlags.ObjectModify | // tells client you can modify the object
753 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
754 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
755 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
756 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
757 PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object
758 );
759
760 const uint LOCKED_GOD_FLAGS = (uint)(
761 PrimFlags.ObjectCopy | // Tells client you can copy the object
762 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
763 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
764 PrimFlags.ObjectAnyOwner // Tells client that someone owns the object
765 );
766
767 const uint SHAREDMASK = (uint)(
768 PermissionMask.Move |
769 PermissionMask.Modify |
770 PermissionMask.Copy
771 );
772
773 public uint GenerateClientFlags(SceneObjectPart task, ScenePresence sp, uint curEffectivePerms)
774 {
775 if(sp == null || task == null || curEffectivePerms == 0)
776 return 0;
606 777
607 // These temporary objectflags get computed and added in this function based on the 778 // Remove any of the objectFlags that are temporary. These will get added back if appropriate
608 // Permission mask that's appropriate! 779 uint objflags = curEffectivePerms & NOT_DEFAULT_FLAGS ;
609 // Outside of this method, they should never be added to objectflags!
610 // -teravus
611 780
612 SceneObjectPart task = m_scene.GetSceneObjectPart(objID); 781 uint returnMask;
613 782
614 // this shouldn't ever happen.. return no permissions/objectflags. 783 SceneObjectGroup grp = task.ParentGroup;
615 if (task == null) 784 if(grp == null)
616 return (uint)0; 785 return 0;
617 786
618 uint objflags = task.GetEffectiveObjectFlags(); 787 UUID taskOwnerID = task.OwnerID;
619 UUID objectOwner = task.OwnerID; 788 UUID spID = sp.UUID;
620 789
790 bool unlocked = (grp.RootPart.OwnerMask & (uint)PermissionMask.Move) != 0;
621 791
622 // Remove any of the objectFlags that are temporary. These will get added back if appropriate 792 if(sp.IsGod)
623 // in the next bit of code 793 {
624 794 // do locked on objects owned by admin
625 // libomv will moan about PrimFlags.ObjectYouOfficer being 795 if(!unlocked && spID == taskOwnerID)
626 // deprecated 796 return objflags | LOCKED_GOD_FLAGS;
627#pragma warning disable 0612 797 else
628 objflags &= (uint) 798 return objflags | GOD_FLAGS;
629 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object 799 }
630 PrimFlags.ObjectModify | // tells client you can modify the object 800
631 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) 801 //bypass option == owner rights
632 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it 802 if (m_bypassPermissions)
633 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object 803 {
634 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object 804 returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags, true); //??
635 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object 805 returnMask |= EXTRAOWNERMASK;
636 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set 806 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
637 ); 807 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
638#pragma warning restore 0612 808 return returnMask;
639 809 }
640 // Creating the three ObjectFlags options for this method to choose from. 810
641 // Customize the OwnerMask 811 // owner
642 uint objectOwnerMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); 812 if (spID == taskOwnerID)
643 objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify; 813 {
644 814 returnMask = ApplyObjectModifyMasks(grp.EffectiveOwnerPerms, objflags, unlocked);
645 // Customize the GroupMask 815 returnMask |= EXTRAOWNERMASK;
646 uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); 816 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
647 817 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
648 // Customize the EveryoneMask 818 return returnMask;
649 uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); 819 }
650 if (objectOwner != UUID.Zero) 820
651 objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; 821 // if not god or owner, do attachments as everyone
652 822 if(task.ParentGroup.IsAttachment)
653 PermissionClass permissionClass = GetPermissionClass(user, task); 823 {
654 824 returnMask = ApplyObjectModifyMasks(grp.EffectiveEveryOnePerms, objflags, unlocked);
655 switch (permissionClass) 825 if (taskOwnerID != UUID.Zero)
826 returnMask |= (uint)PrimFlags.ObjectAnyOwner;
827 return returnMask;
828 }
829
830 UUID taskGroupID = task.GroupID;
831 bool notGroupdOwned = taskOwnerID != taskGroupID;
832
833 // if friends with rights then owner
834 if (notGroupdOwned && IsFriendWithPerms(spID, taskOwnerID))
835 {
836 returnMask = ApplyObjectModifyMasks(grp.EffectiveOwnerPerms, objflags, unlocked);
837 returnMask |= EXTRAOWNERMASK;
838 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
839 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
840 return returnMask;
841 }
842
843 // group owned or shared ?
844 IClientAPI client = sp.ControllingClient;
845 ulong powers = 0;
846 if(taskGroupID != UUID.Zero && GroupMemberPowers(taskGroupID, sp, ref powers))
656 { 847 {
657 case PermissionClass.Owner: 848 if(notGroupdOwned)
658 return objectOwnerMask; 849 {
659 case PermissionClass.Group: 850 // group sharing or everyone
660 return objectGroupMask | objectEveryoneMask; 851 returnMask = ApplyObjectModifyMasks(grp.EffectiveGroupOrEveryOnePerms, objflags, unlocked);
661 case PermissionClass.Everyone: 852 if (taskOwnerID != UUID.Zero)
662 default: 853 returnMask |= (uint)PrimFlags.ObjectAnyOwner;
663 return objectEveryoneMask; 854 return returnMask;
855 }
856
857 // object is owned by group, check role powers
858 if((powers & (ulong)GroupPowers.ObjectManipulate) == 0)
859 {
860 // group sharing or everyone
861 returnMask = ApplyObjectModifyMasks(grp.EffectiveGroupOrEveryOnePerms, objflags, unlocked);
862 returnMask |=
863 (uint)PrimFlags.ObjectGroupOwned |
864 (uint)PrimFlags.ObjectAnyOwner;
865 return returnMask;
866 }
867
868 // we may have copy without transfer
869 uint grpEffectiveOwnerPerms = grp.EffectiveOwnerPerms;
870 if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
871 grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy;
872 returnMask = ApplyObjectModifyMasks(grpEffectiveOwnerPerms, objflags, unlocked);
873 returnMask |=
874 (uint)PrimFlags.ObjectGroupOwned |
875 (uint)PrimFlags.ObjectYouOwner;
876 if((returnMask & (uint)PrimFlags.ObjectModify) != 0)
877 returnMask |= (uint)PrimFlags.ObjectOwnerModify;
878 return returnMask;
664 } 879 }
880
881 // fallback is everyone rights
882 returnMask = ApplyObjectModifyMasks(grp.EffectiveEveryOnePerms, objflags, unlocked);
883 if (taskOwnerID != UUID.Zero)
884 returnMask |= (uint)PrimFlags.ObjectAnyOwner;
885 return returnMask;
665 } 886 }
666 887
667 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) 888 private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask, bool unlocked)
668 { 889 {
669 // We are adding the temporary objectflags to the object's objectflags based on the 890 // We are adding the temporary objectflags to the object's objectflags based on the
670 // permission flag given. These change the F flags on the client. 891 // permission flag given. These change the F flags on the client.
@@ -674,14 +895,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions
674 objectFlagsMask |= (uint)PrimFlags.ObjectCopy; 895 objectFlagsMask |= (uint)PrimFlags.ObjectCopy;
675 } 896 }
676 897
677 if ((setPermissionMask & (uint)PermissionMask.Move) != 0) 898 if (unlocked)
678 { 899 {
679 objectFlagsMask |= (uint)PrimFlags.ObjectMove; 900 if ((setPermissionMask & (uint)PermissionMask.Move) != 0)
680 } 901 {
902 objectFlagsMask |= (uint)PrimFlags.ObjectMove;
903 }
681 904
682 if ((setPermissionMask & (uint)PermissionMask.Modify) != 0) 905 if ((setPermissionMask & (uint)PermissionMask.Modify) != 0)
683 { 906 {
684 objectFlagsMask |= (uint)PrimFlags.ObjectModify; 907 objectFlagsMask |= (uint)PrimFlags.ObjectModify;
908 }
685 } 909 }
686 910
687 if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0) 911 if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0)
@@ -692,6 +916,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
692 return objectFlagsMask; 916 return objectFlagsMask;
693 } 917 }
694 918
919 // OARs still need this method that handles offline users
695 public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj) 920 public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj)
696 { 921 {
697 if (obj == null) 922 if (obj == null)
@@ -705,135 +930,199 @@ namespace OpenSim.Region.CoreModules.World.Permissions
705 if (user == objectOwner) 930 if (user == objectOwner)
706 return PermissionClass.Owner; 931 return PermissionClass.Owner;
707 932
708 if (IsFriendWithPerms(user, objectOwner))
709 return PermissionClass.Owner;
710
711 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
712 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
713 return PermissionClass.Owner;
714
715 // Admin should be able to edit anything in the sim (including admin objects) 933 // Admin should be able to edit anything in the sim (including admin objects)
716 if (IsAdministrator(user)) 934 if (IsAdministrator(user))
717 return PermissionClass.Owner; 935 return PermissionClass.Owner;
718 936
719 // Users should be able to edit what is over their land. 937 if(!obj.ParentGroup.IsAttachment)
720 Vector3 taskPos = obj.AbsolutePosition;
721 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
722 if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
723 { 938 {
724 // Admin objects should not be editable by the above 939 if (IsFriendWithPerms(user, objectOwner) )
725 if (!IsAdministrator(objectOwner))
726 return PermissionClass.Owner; 940 return PermissionClass.Owner;
727 }
728 941
729 // Group permissions 942 // Group permissions
730 if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0)) 943 if (obj.GroupID != UUID.Zero && IsGroupMember(obj.GroupID, user, 0))
731 return PermissionClass.Group; 944 return PermissionClass.Group;
945 }
732 946
733 return PermissionClass.Everyone; 947 return PermissionClass.Everyone;
734 } 948 }
735 949
736 /// <summary> 950 // get effective object permissions using user UUID. User rights will be fixed
737 /// General permissions checks for any operation involving an object. These supplement more specific checks 951 protected uint GetObjectPermissions(UUID currentUser, SceneObjectGroup group, bool denyOnLocked)
738 /// implemented by callers.
739 /// </summary>
740 /// <param name="currentUser"></param>
741 /// <param name="objId">This is a scene object group UUID</param>
742 /// <param name="denyOnLocked"></param>
743 /// <returns></returns>
744 protected bool GenericObjectPermission(UUID currentUser, UUID objId, bool denyOnLocked)
745 { 952 {
746 // Default: deny 953 if (group == null)
747 bool permission = false; 954 return 0;
748 bool locked = false;
749
750 SceneObjectPart part = m_scene.GetSceneObjectPart(objId);
751 955
752 if (part == null) 956 SceneObjectPart root = group.RootPart;
753 return false; 957 if (root == null)
754 958 return 0;
755 SceneObjectGroup group = part.ParentGroup;
756 959
757 UUID objectOwner = group.OwnerID; 960 UUID objectOwner = group.OwnerID;
758 locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); 961 bool locked = denyOnLocked && ((root.OwnerMask & (uint)PermissionMask.Move) == 0);
759 962
760 // People shouldn't be able to do anything with locked objects, except the Administrator 963 if (IsAdministrator(currentUser))
761 // The 'set permissions' runs through a different permission check, so when an object owner
762 // sets an object locked, the only thing that they can do is unlock it.
763 //
764 // Nobody but the object owner can set permissions on an object
765 //
766 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
767 { 964 {
768 return false; 965 // do lock on admin owned objects
966 if(locked && currentUser == objectOwner)
967 return (uint)(PermissionMask.AllEffective & ~(PermissionMask.Modify | PermissionMask.Move));
968 return (uint)PermissionMask.AllEffective;
769 } 969 }
770 970
771 // Object owners should be able to edit their own content 971 uint lockmask = (uint)PermissionMask.AllEffective;
972 if(locked)
973 lockmask &= ~(uint)(PermissionMask.Modify | PermissionMask.Move);
974
772 if (currentUser == objectOwner) 975 if (currentUser == objectOwner)
976 return group.EffectiveOwnerPerms & lockmask;
977
978 if (group.IsAttachment)
979 return 0;
980
981 UUID sogGroupID = group.GroupID;
982 bool notgroudOwned = sogGroupID != objectOwner;
983
984 if (notgroudOwned && IsFriendWithPerms(currentUser, objectOwner))
985 return group.EffectiveOwnerPerms & lockmask;
986
987 ulong powers = 0;
988 if (sogGroupID != UUID.Zero && GroupMemberPowers(sogGroupID, currentUser, ref powers))
773 { 989 {
774 // there is no way that later code can change this back to false 990 if(notgroudOwned)
775 // so just return true immediately and short circuit the more 991 return group.EffectiveGroupOrEveryOnePerms & lockmask;
776 // expensive group checks 992
777 return true; 993 if((powers & (ulong)GroupPowers.ObjectManipulate) == 0)
778 994 return group.EffectiveGroupOrEveryOnePerms & lockmask;
779 //permission = true; 995
996 uint grpEffectiveOwnerPerms = group.EffectiveOwnerPerms & lockmask;
997 if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
998 grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy;
999 return grpEffectiveOwnerPerms;
780 } 1000 }
781 else if (group.IsAttachment) 1001
1002 return group.EffectiveEveryOnePerms & lockmask;
1003 }
1004
1005 // get effective object permissions using present presence. So some may depend on requested rights (ie God)
1006 protected uint GetObjectPermissions(ScenePresence sp, SceneObjectGroup group, bool denyOnLocked)
1007 {
1008 if (sp == null || sp.IsDeleted || group == null || group.IsDeleted)
1009 return 0;
1010
1011 SceneObjectPart root = group.RootPart;
1012 if (root == null)
1013 return 0;
1014
1015 UUID spID = sp.UUID;
1016 UUID objectOwner = group.OwnerID;
1017
1018 bool locked = denyOnLocked && ((root.OwnerMask & (uint)PermissionMask.Move) == 0);
1019
1020 if (sp.IsGod)
782 { 1021 {
783 permission = false; 1022 if(locked && spID == objectOwner)
1023 return (uint)(PermissionMask.AllEffective & ~(PermissionMask.Modify | PermissionMask.Move));
1024 return (uint)PermissionMask.AllEffective;
784 } 1025 }
785 1026
786// m_log.DebugFormat( 1027 uint lockmask = (uint)PermissionMask.AllEffective;
787// "[PERMISSIONS]: group.GroupID = {0}, part.GroupMask = {1}, isGroupMember = {2} for {3}", 1028 if(locked)
788// group.GroupID, 1029 lockmask &= ~(uint)(PermissionMask.Modify | PermissionMask.Move);
789// m_scene.GetSceneObjectPart(objId).GroupMask, 1030
790// IsGroupMember(group.GroupID, currentUser, 0), 1031 if (spID == objectOwner)
791// currentUser); 1032 return group.EffectiveOwnerPerms & lockmask;
792 1033
793 // Group members should be able to edit group objects 1034 if (group.IsAttachment)
794 if ((group.GroupID != UUID.Zero) 1035 return 0;
795 && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) 1036
796 && IsGroupMember(group.GroupID, currentUser, 0)) 1037 UUID sogGroupID = group.GroupID;
797 { 1038 bool notgroudOwned = sogGroupID != objectOwner;
798 // Return immediately, so that the administrator can shares group objects
799 return true;
800 }
801 1039
802 // Friends with benefits should be able to edit the objects too 1040 if (notgroudOwned && IsFriendWithPerms(spID, objectOwner))
803 if (IsFriendWithPerms(currentUser, objectOwner)) 1041 return group.EffectiveOwnerPerms & lockmask;
804 {
805 // Return immediately, so that the administrator can share objects with friends
806 return true;
807 }
808
809 // Users should be able to edit what is over their land.
810 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y);
811 if ((parcel != null) && (parcel.LandData.OwnerID == currentUser))
812 {
813 permission = true;
814 }
815 1042
816 // Estate users should be able to edit anything in the sim 1043 ulong powers = 0;
817 if (IsEstateManager(currentUser)) 1044 if (sogGroupID != UUID.Zero && GroupMemberPowers(sogGroupID, sp, ref powers))
818 { 1045 {
819 permission = true; 1046 if(notgroudOwned)
1047 return group.EffectiveGroupOrEveryOnePerms & lockmask;
1048
1049 if((powers & (ulong)GroupPowers.ObjectManipulate) == 0)
1050 return group.EffectiveGroupOrEveryOnePerms & lockmask;
1051
1052 uint grpEffectiveOwnerPerms = group.EffectiveOwnerPerms & lockmask;
1053 if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1054 grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy;
1055 return grpEffectiveOwnerPerms;
820 } 1056 }
821 1057
822 // Admin objects should not be editable by the above 1058 return group.EffectiveEveryOnePerms & lockmask;
823 if (IsAdministrator(objectOwner)) 1059 }
1060
1061 private uint GetObjectItemPermissions(UUID userID, TaskInventoryItem ti)
1062 {
1063 UUID tiOwnerID = ti.OwnerID;
1064 if(tiOwnerID == userID)
1065 return ti.CurrentPermissions;
1066
1067 if(IsAdministrator(userID))
1068 return (uint)PermissionMask.AllEffective;
1069 // ??
1070 if (IsFriendWithPerms(userID, tiOwnerID))
1071 return ti.CurrentPermissions;
1072
1073 UUID tiGroupID = ti.GroupID;
1074 if(tiGroupID != UUID.Zero)
824 { 1075 {
825 permission = false; 1076 ulong powers = 0;
1077 if(GroupMemberPowers(tiGroupID, userID, ref powers))
1078 {
1079 if(tiGroupID == ti.OwnerID)
1080 {
1081 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1082 return ti.CurrentPermissions;
1083 }
1084 return ti.GroupPermissions;
1085 }
826 } 1086 }
827 1087
828 // Admin should be able to edit anything in the sim (including admin objects) 1088 return 0;
829 if (IsAdministrator(currentUser)) 1089 }
1090
1091 private uint GetObjectItemPermissions(ScenePresence sp, TaskInventoryItem ti, bool notEveryone)
1092 {
1093 UUID tiOwnerID = ti.OwnerID;
1094 UUID spID = sp.UUID;
1095
1096 if(tiOwnerID == spID)
1097 return ti.CurrentPermissions;
1098
1099 // ??
1100 if (IsFriendWithPerms(spID, tiOwnerID))
1101 return ti.CurrentPermissions;
1102
1103 UUID tiGroupID = ti.GroupID;
1104 if(tiGroupID != UUID.Zero)
830 { 1105 {
831 permission = true; 1106 ulong powers = 0;
1107 if(GroupMemberPowers(tiGroupID, spID, ref powers))
1108 {
1109 if(tiGroupID == ti.OwnerID)
1110 {
1111 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1112 return ti.CurrentPermissions;
1113 }
1114 uint p = ti.GroupPermissions;
1115 if(!notEveryone)
1116 p |= ti.EveryonePermissions;
1117 return p;
1118 }
832 } 1119 }
833 1120
834 return permission; 1121 if(notEveryone)
835 } 1122 return 0;
836 1123
1124 return ti.EveryonePermissions;
1125 }
837 #endregion 1126 #endregion
838 1127
839 #region Generic Permissions 1128 #region Generic Permissions
@@ -858,97 +1147,45 @@ namespace OpenSim.Region.CoreModules.World.Permissions
858 1147
859 public bool GenericEstatePermission(UUID user) 1148 public bool GenericEstatePermission(UUID user)
860 { 1149 {
861 // Default: deny
862 bool permission = false;
863
864 // Estate admins should be able to use estate tools 1150 // Estate admins should be able to use estate tools
865 if (IsEstateManager(user)) 1151 if (IsEstateManager(user))
866 permission = true; 1152 return true;
867 1153
868 // Administrators always have permission 1154 // Administrators always have permission
869 if (IsAdministrator(user)) 1155 if (IsAdministrator(user))
870 permission = true; 1156 return true;
871 1157
872 return permission; 1158 return false;
873 } 1159 }
874 1160
875 protected bool GenericParcelPermission(UUID user, ILandObject parcel, ulong groupPowers)
876 {
877 bool permission = false;
878
879 if (parcel.LandData.OwnerID == user)
880 {
881 permission = true;
882 }
883
884 if ((parcel.LandData.GroupID != UUID.Zero) && IsGroupMember(parcel.LandData.GroupID, user, groupPowers))
885 {
886 permission = true;
887 }
888
889 if (IsEstateManager(user))
890 {
891 permission = true;
892 }
893
894 if (IsAdministrator(user))
895 {
896 permission = true;
897 }
898
899 if (m_SimpleBuildPermissions &&
900 (parcel.LandData.Flags & (uint)ParcelFlags.UseAccessList) == 0 && parcel.IsInLandAccessList(user))
901 permission = true;
902
903 return permission;
904 }
905
906 protected bool GenericParcelOwnerPermission(UUID user, ILandObject parcel, ulong groupPowers, bool allowEstateManager) 1161 protected bool GenericParcelOwnerPermission(UUID user, ILandObject parcel, ulong groupPowers, bool allowEstateManager)
907 { 1162 {
908 if (parcel.LandData.OwnerID == user) 1163 if (parcel.LandData.OwnerID == user)
909 {
910 // Returning immediately so that group deeded objects on group deeded land don't trigger a NRE on
911 // the subsequent redundant checks when using lParcelMediaCommandList()
912 // See http://opensimulator.org/mantis/view.php?id=3999 for more details
913 return true; 1164 return true;
914 }
915 1165
916 if (parcel.LandData.IsGroupOwned && IsGroupMember(parcel.LandData.GroupID, user, groupPowers)) 1166 if (parcel.LandData.IsGroupOwned && IsGroupMember(parcel.LandData.GroupID, user, groupPowers))
917 {
918 return true; 1167 return true;
919 } 1168
920
921 if (allowEstateManager && IsEstateManager(user)) 1169 if (allowEstateManager && IsEstateManager(user))
922 {
923 return true; 1170 return true;
924 }
925 1171
926 if (IsAdministrator(user)) 1172 if (IsAdministrator(user))
927 {
928 return true; 1173 return true;
929 }
930 1174
931 return false; 1175 return false;
932 } 1176 }
933
934 protected bool GenericParcelPermission(UUID user, Vector3 pos, ulong groupPowers)
935 {
936 ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
937 if (parcel == null) return false;
938 return GenericParcelPermission(user, parcel, groupPowers);
939 }
940#endregion 1177#endregion
941 1178
942 #region Permission Checks 1179 #region Permission Checks
943 private bool CanAbandonParcel(UUID user, ILandObject parcel, Scene scene) 1180 private bool CanAbandonParcel(UUID user, ILandObject parcel)
944 { 1181 {
945 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1182 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
946 if (m_bypassPermissions) return m_bypassPermissionsValue; 1183 if (m_bypassPermissions) return m_bypassPermissionsValue;
947 1184
948 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandRelease, false); 1185 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandRelease, false);
949 } 1186 }
950 1187
951 private bool CanReclaimParcel(UUID user, ILandObject parcel, Scene scene) 1188 private bool CanReclaimParcel(UUID user, ILandObject parcel)
952 { 1189 {
953 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1190 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
954 if (m_bypassPermissions) return m_bypassPermissionsValue; 1191 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -956,108 +1193,252 @@ namespace OpenSim.Region.CoreModules.World.Permissions
956 return GenericParcelOwnerPermission(user, parcel, 0,true); 1193 return GenericParcelOwnerPermission(user, parcel, 0,true);
957 } 1194 }
958 1195
959 private bool CanDeedParcel(UUID user, ILandObject parcel, Scene scene) 1196 private bool CanDeedParcel(UUID user, ILandObject parcel)
960 { 1197 {
961 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1198 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
962 if (m_bypassPermissions) return m_bypassPermissionsValue; 1199 if (m_bypassPermissions) return m_bypassPermissionsValue;
963 1200
1201 if(parcel.LandData.GroupID == UUID.Zero)
1202 return false;
1203
1204 if (IsAdministrator(user))
1205 return true;
1206
964 if (parcel.LandData.OwnerID != user) // Only the owner can deed! 1207 if (parcel.LandData.OwnerID != user) // Only the owner can deed!
965 return false; 1208 return false;
966 1209
967 ScenePresence sp = scene.GetScenePresence(user); 1210 ScenePresence sp = m_scene.GetScenePresence(user);
968 IClientAPI client = sp.ControllingClient; 1211 if(sp == null)
1212 return false;
969 1213
1214 IClientAPI client = sp.ControllingClient;
970 if ((client.GetGroupPowers(parcel.LandData.GroupID) & (ulong)GroupPowers.LandDeed) == 0) 1215 if ((client.GetGroupPowers(parcel.LandData.GroupID) & (ulong)GroupPowers.LandDeed) == 0)
971 return false; 1216 return false;
972 1217
973 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandDeed, false); 1218 return true;
974 } 1219 }
975 1220
976 private bool CanDeedObject(UUID user, UUID group, Scene scene) 1221 private bool CanDeedObject(ScenePresence sp, SceneObjectGroup sog, UUID targetGroupID)
977 { 1222 {
978 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1223 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
979 if (m_bypassPermissions) return m_bypassPermissionsValue; 1224 if (m_bypassPermissions) return m_bypassPermissionsValue;
980 1225
981 ScenePresence sp = scene.GetScenePresence(user); 1226 if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted || targetGroupID == UUID.Zero)
982 IClientAPI client = sp.ControllingClient; 1227 return false;
1228
1229 // object has group already?
1230 if(sog.GroupID != targetGroupID)
1231 return false;
1232
1233 // is effectivelly shared?
1234 if(sog.EffectiveGroupPerms == 0)
1235 return false;
1236
1237 if(sp.IsGod)
1238 return true;
1239
1240 // owned by requester?
1241 if(sog.OwnerID != sp.UUID)
1242 return false;
1243
1244 // owner can transfer?
1245 if((sog.EffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1246 return false;
1247
1248 // group member ?
1249 ulong powers = 0;
1250 if(!GroupMemberPowers(targetGroupID, sp, ref powers))
1251 return false;
983 1252
984 if ((client.GetGroupPowers(group) & (ulong)GroupPowers.DeedObject) == 0) 1253 // has group rights?
1254 if ((powers & (ulong)GroupPowers.DeedObject) == 0)
985 return false; 1255 return false;
986 1256
987 return true; 1257 return true;
988 } 1258 }
989 1259
990 private bool IsGod(UUID user, Scene scene) 1260 private bool CanDuplicateObject(SceneObjectGroup sog, ScenePresence sp)
991 { 1261 {
992 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1262 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
993 if (m_bypassPermissions) return m_bypassPermissionsValue; 1263 if (m_bypassPermissions) return m_bypassPermissionsValue;
994 1264
995 return IsAdministrator(user); 1265 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1266 return false;
1267
1268 uint perms = GetObjectPermissions(sp, sog, false);
1269 if((perms & (uint)PermissionMask.Copy) == 0)
1270 return false;
1271
1272 if(sog.OwnerID != sp.UUID && (perms & (uint)PermissionMask.Transfer) == 0)
1273 return false;
1274
1275 //If they can rez, they can duplicate
1276 return CanRezObject(0, sp.UUID, sog.AbsolutePosition);
996 } 1277 }
997 1278
998 private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition) 1279 private bool CanDeleteObject(SceneObjectGroup sog, ScenePresence sp)
999 { 1280 {
1281 // ignoring locked. viewers should warn and ask for confirmation
1282
1000 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1283 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1001 if (m_bypassPermissions) return m_bypassPermissionsValue; 1284 if (m_bypassPermissions) return m_bypassPermissionsValue;
1002 1285
1003 if (!GenericObjectPermission(owner, objectID, true)) 1286 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1004 {
1005 //They can't even edit the object
1006 return false; 1287 return false;
1007 } 1288
1008 1289 if(sog.IsAttachment)
1009 SceneObjectPart part = scene.GetSceneObjectPart(objectID);
1010 if (part == null)
1011 return false; 1290 return false;
1012 1291
1013 if (part.OwnerID == owner) 1292 UUID sogOwnerID = sog.OwnerID;
1293 UUID spID = sp.UUID;
1294
1295 if(sogOwnerID == spID)
1296 return true;
1297
1298 if (sp.IsGod)
1299 return true;
1300
1301 if (IsFriendWithPerms(sog.UUID, sogOwnerID))
1302 return true;
1303
1304 UUID sogGroupID = sog.GroupID;
1305 if (sogGroupID != UUID.Zero)
1014 { 1306 {
1015 if ((part.OwnerMask & PERM_COPY) == 0) 1307 ulong powers = 0;
1016 return false; 1308 if(GroupMemberPowers(sogGroupID, sp, ref powers))
1309 {
1310 if(sogGroupID == sogOwnerID)
1311 {
1312 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1313 return true;
1314 }
1315 return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0;
1316 }
1017 } 1317 }
1018 else if (part.GroupID != UUID.Zero) 1318 return false;
1019 { 1319 }
1020 if ((part.OwnerID == part.GroupID) && ((owner != part.LastOwnerID) || ((part.GroupMask & PERM_TRANS) == 0)))
1021 return false;
1022 1320
1023 if ((part.GroupMask & PERM_COPY) == 0) 1321 private bool CanDeleteObjectByIDs(UUID objectID, UUID userID)
1024 return false; 1322 {
1323 // ignoring locked. viewers should warn and ask for confirmation
1324
1325 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1326 if (m_bypassPermissions) return m_bypassPermissionsValue;
1327
1328 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
1329 if (sog == null)
1330 return false;
1331
1332 if(sog.IsAttachment)
1333 return false;
1334
1335 UUID sogOwnerID = sog.OwnerID;
1336
1337 if(sogOwnerID == userID)
1338 return true;
1339
1340 if (IsAdministrator(userID))
1341 return true;
1342
1343 if (IsFriendWithPerms(objectID, sogOwnerID))
1344 return true;
1345
1346 UUID sogGroupID = sog.GroupID;
1347 if (sogGroupID != UUID.Zero)
1348 {
1349 ulong powers = 0;
1350 if(GroupMemberPowers(sogGroupID, userID, ref powers))
1351 {
1352 if(sogGroupID == sogOwnerID)
1353 {
1354 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1355 return true;
1356 }
1357 return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0;
1358 }
1025 } 1359 }
1026 1360 return false;
1027 //If they can rez, they can duplicate 1361 }
1028 return CanRezObject(objectCount, owner, objectPosition, scene); 1362
1363 private bool CanEditObjectByIDs(UUID objectID, UUID userID)
1364 {
1365 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1366 if (m_bypassPermissions) return m_bypassPermissionsValue;
1367
1368 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
1369 if (sog == null)
1370 return false;
1371
1372 uint perms = GetObjectPermissions(userID, sog, true);
1373 if((perms & (uint)PermissionMask.Modify) == 0)
1374 return false;
1375 return true;
1029 } 1376 }
1030 1377
1031 private bool CanDeleteObject(UUID objectID, UUID deleter, Scene scene) 1378 private bool CanEditObject(SceneObjectGroup sog, ScenePresence sp)
1032 { 1379 {
1033 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1380 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1034 if (m_bypassPermissions) return m_bypassPermissionsValue; 1381 if (m_bypassPermissions) return m_bypassPermissionsValue;
1035 1382
1036 return GenericObjectPermission(deleter, objectID, false); 1383 if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1384 return false;
1385
1386 uint perms = GetObjectPermissions(sp, sog, true);
1387 if((perms & (uint)PermissionMask.Modify) == 0)
1388 return false;
1389 return true;
1037 } 1390 }
1038 1391
1039 private bool CanEditObject(UUID objectID, UUID editorID, Scene scene) 1392 private bool CanEditObjectPerms(SceneObjectGroup sog, UUID userID)
1040 { 1393 {
1041 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1394 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1042 if (m_bypassPermissions) return m_bypassPermissionsValue; 1395 if (m_bypassPermissions) return m_bypassPermissionsValue;
1043 1396
1044 return GenericObjectPermission(editorID, objectID, false); 1397 if (sog == null)
1398 return false;
1399
1400 if(sog.OwnerID == userID || IsAdministrator(userID))
1401 return true;
1402
1403 UUID sogGroupID = sog.GroupID;
1404 if(sogGroupID == UUID.Zero || sogGroupID != sog.OwnerID)
1405 return false;
1406
1407 uint perms = sog.EffectiveOwnerPerms;
1408 if((perms & (uint)PermissionMask.Modify) == 0)
1409 return false;
1410
1411 ulong powers = 0;
1412 if(GroupMemberPowers(sogGroupID, userID, ref powers))
1413 {
1414 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1415 return true;
1416 }
1417
1418 return false;
1045 } 1419 }
1046 1420
1047 private bool CanEditObjectInventory(UUID objectID, UUID editorID, Scene scene) 1421 private bool CanEditObjectInventory(UUID objectID, UUID userID)
1048 { 1422 {
1049 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1423 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1050 if (m_bypassPermissions) return m_bypassPermissionsValue; 1424 if (m_bypassPermissions) return m_bypassPermissionsValue;
1051 1425
1052 return GenericObjectPermission(editorID, objectID, false); 1426 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
1427 if (sog == null)
1428 return false;
1429
1430 uint perms = GetObjectPermissions(userID, sog, true);
1431 if((perms & (uint)PermissionMask.Modify) == 0)
1432 return false;
1433 return true;
1053 } 1434 }
1054 1435
1055 private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene) 1436 private bool CanEditParcelProperties(UUID userID, ILandObject parcel, GroupPowers p, bool allowManager)
1056 { 1437 {
1057 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1438 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1058 if (m_bypassPermissions) return m_bypassPermissionsValue; 1439 if (m_bypassPermissions) return m_bypassPermissionsValue;
1059 1440
1060 return GenericParcelOwnerPermission(user, parcel, (ulong)p, false); 1441 return GenericParcelOwnerPermission(userID, parcel, (ulong)p, false);
1061 } 1442 }
1062 1443
1063 /// <summary> 1444 /// <summary>
@@ -1068,18 +1449,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1068 /// <param name="user"></param> 1449 /// <param name="user"></param>
1069 /// <param name="scene"></param> 1450 /// <param name="scene"></param>
1070 /// <returns></returns> 1451 /// <returns></returns>
1071 private bool CanEditScript(UUID script, UUID objectID, UUID user, Scene scene) 1452 private bool CanEditScript(UUID script, UUID objectID, UUID userID)
1072 { 1453 {
1073 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1454 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1074 if (m_bypassPermissions) return m_bypassPermissionsValue; 1455 if (m_bypassPermissions) return m_bypassPermissionsValue;
1075 1456
1076 if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(user)) 1457 if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(userID))
1077 return false; 1458 return false;
1078 1459
1079 // Ordinarily, if you can view it, you can edit it 1460 // Ordinarily, if you can view it, you can edit it
1080 // There is no viewing a no mod script 1461 // There is no viewing a no mod script
1081 // 1462 //
1082 return CanViewScript(script, objectID, user, scene); 1463 return CanViewScript(script, objectID, userID);
1083 } 1464 }
1084 1465
1085 /// <summary> 1466 /// <summary>
@@ -1090,7 +1471,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1090 /// <param name="user"></param> 1471 /// <param name="user"></param>
1091 /// <param name="scene"></param> 1472 /// <param name="scene"></param>
1092 /// <returns></returns> 1473 /// <returns></returns>
1093 private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) 1474 private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user)
1094 { 1475 {
1095 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1476 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1096 if (m_bypassPermissions) return m_bypassPermissionsValue; 1477 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1098,8 +1479,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1098 if (objectID == UUID.Zero) // User inventory 1479 if (objectID == UUID.Zero) // User inventory
1099 { 1480 {
1100 IInventoryService invService = m_scene.InventoryService; 1481 IInventoryService invService = m_scene.InventoryService;
1101 InventoryItemBase assetRequestItem = new InventoryItemBase(notecard, user); 1482 InventoryItemBase assetRequestItem = invService.GetItem(user, notecard);
1102 assetRequestItem = invService.GetItem(assetRequestItem);
1103 if (assetRequestItem == null && LibraryRootFolder != null) // Library item 1483 if (assetRequestItem == null && LibraryRootFolder != null) // Library item
1104 { 1484 {
1105 assetRequestItem = LibraryRootFolder.FindItem(notecard); 1485 assetRequestItem = LibraryRootFolder.FindItem(notecard);
@@ -1122,69 +1502,68 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1122 } 1502 }
1123 else // Prim inventory 1503 else // Prim inventory
1124 { 1504 {
1125 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 1505 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1126
1127 if (part == null) 1506 if (part == null)
1128 return false; 1507 return false;
1129 1508
1130 if (part.OwnerID != user) 1509 SceneObjectGroup sog = part.ParentGroup;
1131 { 1510 if (sog == null)
1132 if (part.GroupID == UUID.Zero) 1511 return false;
1133 return false;
1134 1512
1135 if (!IsGroupMember(part.GroupID, user, 0)) 1513 // check object mod right
1136 return false; 1514 uint perms = GetObjectPermissions(user, sog, true);
1137 1515 if((perms & (uint)PermissionMask.Modify) == 0)
1138 if ((part.GroupMask & (uint)PermissionMask.Modify) == 0)
1139 return false;
1140 }
1141 else
1142 {
1143 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1144 return false; 1516 return false;
1145 }
1146 1517
1147 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); 1518 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard);
1148
1149 if (ti == null) 1519 if (ti == null)
1150 return false; 1520 return false;
1151 1521
1152 if (ti.OwnerID != user) 1522 if (ti.OwnerID != user)
1153 { 1523 {
1154 if (ti.GroupID == UUID.Zero) 1524 UUID tiGroupID = ti.GroupID;
1525 if (tiGroupID == UUID.Zero)
1155 return false; 1526 return false;
1156 1527
1157 if (!IsGroupMember(ti.GroupID, user, 0)) 1528 ulong powers = 0;
1529 if(!GroupMemberPowers(tiGroupID, user, ref powers))
1158 return false; 1530 return false;
1531
1532 if(tiGroupID == ti.OwnerID && (powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1533 {
1534 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) ==
1535 ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy))
1536 return true;
1537 }
1538 if ((ti.GroupPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) ==
1539 ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy))
1540 return true;
1541 return false;
1159 } 1542 }
1160 1543
1161 // Require full perms 1544 // Require full perms
1162 if ((ti.CurrentPermissions & 1545 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) !=
1163 ((uint)PermissionMask.Modify | 1546 ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy))
1164 (uint)PermissionMask.Copy)) !=
1165 ((uint)PermissionMask.Modify |
1166 (uint)PermissionMask.Copy))
1167 return false; 1547 return false;
1168 } 1548 }
1169
1170 return true; 1549 return true;
1171 } 1550 }
1172 1551
1173 private bool CanInstantMessage(UUID user, UUID target, Scene startScene) 1552 private bool CanInstantMessage(UUID user, UUID target)
1174 { 1553 {
1175 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1554 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1176 if (m_bypassPermissions) return m_bypassPermissionsValue; 1555 if (m_bypassPermissions) return m_bypassPermissionsValue;
1177 1556
1178 // If the sender is an object, check owner instead 1557 // If the sender is an object, check owner instead
1179 // 1558 //
1180 SceneObjectPart part = startScene.GetSceneObjectPart(user); 1559 SceneObjectPart part = m_scene.GetSceneObjectPart(user);
1181 if (part != null) 1560 if (part != null)
1182 user = part.OwnerID; 1561 user = part.OwnerID;
1183 1562
1184 return GenericCommunicationPermission(user, target); 1563 return GenericCommunicationPermission(user, target);
1185 } 1564 }
1186 1565
1187 private bool CanInventoryTransfer(UUID user, UUID target, Scene startScene) 1566 private bool CanInventoryTransfer(UUID user, UUID target)
1188 { 1567 {
1189 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1568 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1190 if (m_bypassPermissions) return m_bypassPermissionsValue; 1569 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1192,7 +1571,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1192 return GenericCommunicationPermission(user, target); 1571 return GenericCommunicationPermission(user, target);
1193 } 1572 }
1194 1573
1195 private bool CanIssueEstateCommand(UUID user, Scene requestFromScene, bool ownerCommand) 1574 private bool CanIssueEstateCommand(UUID user, bool ownerCommand)
1196 { 1575 {
1197 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1576 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1198 if (m_bypassPermissions) return m_bypassPermissionsValue; 1577 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1200,174 +1579,161 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1200 if (IsAdministrator(user)) 1579 if (IsAdministrator(user))
1201 return true; 1580 return true;
1202 1581
1203 if (m_scene.RegionInfo.EstateSettings.IsEstateOwner(user))
1204 return true;
1205
1206 if (ownerCommand) 1582 if (ownerCommand)
1207 return false; 1583 return m_scene.RegionInfo.EstateSettings.IsEstateOwner(user);
1208 1584
1209 return GenericEstatePermission(user); 1585 return IsEstateManager(user);
1210 } 1586 }
1211 1587
1212 private bool CanMoveObject(UUID objectID, UUID moverID, Scene scene) 1588 private bool CanMoveObject(SceneObjectGroup sog, ScenePresence sp)
1213 { 1589 {
1214 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1590 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1591
1592 if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1593 return false;
1594
1215 if (m_bypassPermissions) 1595 if (m_bypassPermissions)
1216 { 1596 {
1217 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 1597 if (sog.OwnerID != sp.UUID && sog.IsAttachment)
1218 if (part.OwnerID != moverID) 1598 return false;
1219 {
1220 if (!part.ParentGroup.IsDeleted)
1221 {
1222 if (part.ParentGroup.IsAttachment)
1223 return false;
1224 }
1225 }
1226 return m_bypassPermissionsValue; 1599 return m_bypassPermissionsValue;
1227 } 1600 }
1228 1601
1229 bool permission = GenericObjectPermission(moverID, objectID, true); 1602 uint perms = GetObjectPermissions(sp, sog, true);
1230 if (!permission) 1603 if((perms & (uint)PermissionMask.Move) == 0)
1231 { 1604 return false;
1232 if (!m_scene.Entities.ContainsKey(objectID)) 1605 return true;
1233 { 1606 }
1234 return false;
1235 }
1236 1607
1237 // The client 1608 private bool CanObjectEntry(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint)
1238 // may request to edit linked parts, and therefore, it needs 1609 {
1239 // to also check for SceneObjectPart 1610 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1240 1611
1241 // If it's not an object, we cant edit it. 1612 float newX = newPoint.X;
1242 if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) 1613 float newY = newPoint.Y;
1243 {
1244 return false;
1245 }
1246 1614
1615 // allow outside region this is needed for crossings
1616 if (newX < -1f || newX > (m_scene.RegionInfo.RegionSizeX + 1.0f) ||
1617 newY < -1f || newY > (m_scene.RegionInfo.RegionSizeY + 1.0f) )
1618 return true;
1247 1619
1248 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; 1620 if(sog == null || sog.IsDeleted)
1621 return false;
1249 1622
1623 if (m_bypassPermissions)
1624 return m_bypassPermissionsValue;
1250 1625
1251 // UUID taskOwner = null; 1626 ILandObject parcel = m_scene.LandChannel.GetLandObject(newX, newY);
1252 // Added this because at this point in time it wouldn't be wise for 1627 if (parcel == null)
1253 // the administrator object permissions to take effect. 1628 return false;
1254 // UUID objectOwner = task.OwnerID;
1255 1629
1256 // Anyone can move 1630 if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowAPrimitiveEntry)) != 0)
1257 if ((task.RootPart.EveryoneMask & PERM_MOVE) != 0) 1631 return true;
1258 permission = true;
1259 1632
1260 // Locked 1633 if (!enteringRegion)
1261 if ((task.RootPart.OwnerMask & PERM_LOCKED) == 0)
1262 permission = false;
1263 }
1264 else
1265 { 1634 {
1266 bool locked = false; 1635 Vector3 oldPoint = sog.AbsolutePosition;
1267 if (!m_scene.Entities.ContainsKey(objectID)) 1636 ILandObject fromparcel = m_scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y);
1268 { 1637 if (fromparcel != null && fromparcel.Equals(parcel)) // it already entered parcel ????
1269 return false; 1638 return true;
1270 } 1639 }
1271
1272 // If it's not an object, we cant edit it.
1273 if ((!(m_scene.Entities[objectID] is SceneObjectGroup)))
1274 {
1275 return false;
1276 }
1277 1640
1278 SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objectID]; 1641 UUID userID = sog.OwnerID;
1642 LandData landdata = parcel.LandData;
1279 1643
1280 UUID objectOwner = group.OwnerID; 1644 if (landdata.OwnerID == userID)
1281 locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); 1645 return true;
1282 1646
1283 // This is an exception to the generic object permission. 1647 if (IsAdministrator(userID))
1284 // Administrators who lock their objects should not be able to move them, 1648 return true;
1285 // however generic object permission should return true.
1286 // This keeps locked objects from being affected by random click + drag actions by accident
1287 // and allows the administrator to grab or delete a locked object.
1288 1649
1289 // Administrators and estate managers are still able to click+grab locked objects not 1650 UUID landGroupID = landdata.GroupID;
1290 // owned by them in the scene 1651 if (landGroupID != UUID.Zero)
1291 // This is by design. 1652 {
1653 if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowGroupObjectEntry)) != 0)
1654 return IsGroupMember(landGroupID, userID, 0);
1292 1655
1293 if (locked && (moverID == objectOwner)) 1656 if (landdata.IsGroupOwned && IsGroupMember(landGroupID, userID, (ulong)GroupPowers.AllowRez))
1294 return false; 1657 return true;
1295 } 1658 }
1296 return permission; 1659
1660 //Otherwise, false!
1661 return false;
1297 } 1662 }
1298 1663
1299 private bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) 1664 private bool OnObjectEnterWithScripts(SceneObjectGroup sog, ILandObject parcel)
1300 { 1665 {
1301 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1666 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1302 if (m_bypassPermissions) return m_bypassPermissionsValue;
1303 1667
1304 if ((newPoint.X > 257f || newPoint.X < -1f || newPoint.Y > 257f || newPoint.Y < -1f)) 1668 if(sog == null || sog.IsDeleted)
1305 { 1669 return false;
1306 return true;
1307 }
1308 1670
1309 SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; 1671 if (m_bypassPermissions)
1672 return m_bypassPermissionsValue;
1310 1673
1311 ILandObject land = m_scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); 1674 if (parcel == null)
1675 return true;
1312 1676
1313 if (!enteringRegion) 1677 int checkflags = ((int)ParcelFlags.AllowAPrimitiveEntry);
1314 { 1678 bool scripts = (sog.ScriptCount() > 0);
1315 ILandObject fromland = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); 1679 if(scripts)
1680 checkflags |= ((int)ParcelFlags.AllowOtherScripts);
1316 1681
1317 if (fromland == land) // Not entering 1682 if ((parcel.LandData.Flags & checkflags) == checkflags)
1318 return true; 1683 return true;
1319 }
1320 1684
1321 if (land == null) 1685 UUID userID = sog.OwnerID;
1322 { 1686 LandData landdata = parcel.LandData;
1323 return false;
1324 }
1325 1687
1326 if ((land.LandData.Flags & ((int)ParcelFlags.AllowAPrimitiveEntry)) != 0) 1688 if (landdata.OwnerID == userID)
1327 {
1328 return true; 1689 return true;
1329 }
1330 1690
1331 if (!m_scene.Entities.ContainsKey(objectID)) 1691 if (IsAdministrator(userID))
1332 { 1692 return true;
1333 return false;
1334 }
1335 1693
1336 // If it's not an object, we cant edit it. 1694 UUID landGroupID = landdata.GroupID;
1337 if (!(m_scene.Entities[objectID] is SceneObjectGroup)) 1695 if (landGroupID != UUID.Zero)
1338 { 1696 {
1339 return false; 1697 checkflags = (int)ParcelFlags.AllowGroupObjectEntry;
1340 } 1698 if(scripts)
1699 checkflags |= ((int)ParcelFlags.AllowGroupScripts);
1341 1700
1701 if ((parcel.LandData.Flags & checkflags) == checkflags)
1702 return IsGroupMember(landGroupID, userID, 0);
1342 1703
1343 if (GenericParcelPermission(task.OwnerID, newPoint, 0)) 1704 if (landdata.IsGroupOwned && IsGroupMember(landGroupID, userID, (ulong)GroupPowers.AllowRez))
1344 { 1705 return true;
1345 return true;
1346 } 1706 }
1347 1707
1348 //Otherwise, false! 1708 //Otherwise, false!
1349 return false; 1709 return false;
1350 } 1710 }
1351 1711
1352 private bool CanReturnObjects(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene) 1712 private bool CanReturnObjects(ILandObject land, ScenePresence sp, List<SceneObjectGroup> objects)
1353 { 1713 {
1354 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1714 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1355 if (m_bypassPermissions) return m_bypassPermissionsValue; 1715 if (m_bypassPermissions) return m_bypassPermissionsValue;
1356 1716
1357 GroupPowers powers; 1717 if(sp == null)
1358 ILandObject l; 1718 return true; // assuming that in this case rights are as owner
1359 1719
1360 ScenePresence sp = scene.GetScenePresence(user); 1720 UUID userID = sp.UUID;
1361 if (sp == null) 1721 bool isPrivUser = sp.IsGod || IsEstateManager(userID);
1362 return false;
1363 1722
1364 IClientAPI client = sp.ControllingClient; 1723 IClientAPI client = sp.ControllingClient;
1365 1724
1725 ulong powers = 0;
1726 ILandObject l;
1727
1366 foreach (SceneObjectGroup g in new List<SceneObjectGroup>(objects)) 1728 foreach (SceneObjectGroup g in new List<SceneObjectGroup>(objects))
1367 { 1729 {
1368 // Any user can return their own objects at any time 1730 if(g.IsAttachment)
1369 // 1731 {
1370 if (GenericObjectPermission(user, g.UUID, false)) 1732 objects.Remove(g);
1733 continue;
1734 }
1735
1736 if (isPrivUser || g.OwnerID == userID)
1371 continue; 1737 continue;
1372 1738
1373 // This is a short cut for efficiency. If land is non-null, 1739 // This is a short cut for efficiency. If land is non-null,
@@ -1381,39 +1747,40 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1381 else 1747 else
1382 { 1748 {
1383 Vector3 pos = g.AbsolutePosition; 1749 Vector3 pos = g.AbsolutePosition;
1384 1750 l = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
1385 l = scene.LandChannel.GetLandObject(pos.X, pos.Y);
1386 } 1751 }
1387 1752
1388 // If it's not over any land, then we can't do a thing 1753 // If it's not over any land, then we can't do a thing
1389 if (l == null) 1754 if (l == null || l.LandData == null)
1390 { 1755 {
1391 objects.Remove(g); 1756 objects.Remove(g);
1392 continue; 1757 continue;
1393 } 1758 }
1394 1759
1760 LandData ldata = l.LandData;
1395 // If we own the land outright, then allow 1761 // If we own the land outright, then allow
1396 // 1762 //
1397 if (l.LandData.OwnerID == user) 1763 if (ldata.OwnerID == userID)
1398 continue; 1764 continue;
1399 1765
1400 // Group voodoo 1766 // Group voodoo
1401 // 1767 //
1402 if (l.LandData.IsGroupOwned) 1768 if (ldata.IsGroupOwned)
1403 { 1769 {
1404 powers = (GroupPowers)client.GetGroupPowers(l.LandData.GroupID); 1770 UUID lGroupID = ldata.GroupID;
1405 // Not a group member, or no rights at all 1771 // Not a group member, or no rights at all
1406 // 1772 //
1407 if (powers == (GroupPowers)0) 1773 powers = client.GetGroupPowers(lGroupID);
1774 if(powers == 0)
1408 { 1775 {
1409 objects.Remove(g); 1776 objects.Remove(g);
1410 continue; 1777 continue;
1411 } 1778 }
1412 1779
1413 // Group deeded object? 1780 // Group deeded object?
1414 // 1781 //
1415 if (g.OwnerID == l.LandData.GroupID && 1782 if (g.OwnerID == lGroupID &&
1416 (powers & GroupPowers.ReturnGroupOwned) == (GroupPowers)0) 1783 (powers & (ulong)GroupPowers.ReturnGroupOwned) == 0)
1417 { 1784 {
1418 objects.Remove(g); 1785 objects.Remove(g);
1419 continue; 1786 continue;
@@ -1421,14 +1788,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1421 1788
1422 // Group set object? 1789 // Group set object?
1423 // 1790 //
1424 if (g.GroupID == l.LandData.GroupID && 1791 if (g.GroupID == lGroupID &&
1425 (powers & GroupPowers.ReturnGroupSet) == (GroupPowers)0) 1792 (powers & (ulong)GroupPowers.ReturnGroupSet) == 0)
1426 { 1793 {
1427 objects.Remove(g); 1794 objects.Remove(g);
1428 continue; 1795 continue;
1429 } 1796 }
1430 1797
1431 if ((powers & GroupPowers.ReturnNonGroup) == (GroupPowers)0) 1798 if ((powers & (ulong)GroupPowers.ReturnNonGroup) == 0)
1432 { 1799 {
1433 objects.Remove(g); 1800 objects.Remove(g);
1434 continue; 1801 continue;
@@ -1451,41 +1818,41 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1451 return true; 1818 return true;
1452 } 1819 }
1453 1820
1454 private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) 1821 private bool CanRezObject(int objectCount, UUID userID, Vector3 objectPosition)
1455 { 1822 {
1456 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1823 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1457 if (m_bypassPermissions) return m_bypassPermissionsValue; 1824 if (m_bypassPermissions)
1825 return m_bypassPermissionsValue;
1458 1826
1459// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name); 1827// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
1460 1828
1461 ILandObject parcel = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 1829 ILandObject parcel = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
1462 if (parcel == null) 1830 if (parcel == null || parcel.LandData == null)
1463 return false; 1831 return false;
1464 1832
1465 if ((parcel.LandData.Flags & (uint)ParcelFlags.CreateObjects) != 0) 1833 LandData landdata = parcel.LandData;
1466 { 1834 if ((userID == landdata.OwnerID))
1467 return true;
1468 }
1469 else if ((owner == parcel.LandData.OwnerID) || IsAdministrator(owner))
1470 {
1471 return true; 1835 return true;
1472 } 1836
1473 else if (((parcel.LandData.Flags & (uint)ParcelFlags.CreateGroupObjects) != 0) 1837 if ((landdata.Flags & (uint)ParcelFlags.CreateObjects) != 0)
1474 && (parcel.LandData.GroupID != UUID.Zero) && IsGroupMember(parcel.LandData.GroupID, owner, 0))
1475 {
1476 return true; 1838 return true;
1477 } 1839
1478 else if (parcel.LandData.GroupID != UUID.Zero && IsGroupMember(parcel.LandData.GroupID, owner, (ulong)GroupPowers.AllowRez)) 1840 if(IsAdministrator(userID))
1479 {
1480 return true; 1841 return true;
1481 } 1842
1482 else 1843 if(landdata.GroupID != UUID.Zero)
1483 { 1844 {
1484 return false; 1845 if ((landdata.Flags & (uint)ParcelFlags.CreateGroupObjects) != 0)
1846 return IsGroupMember(landdata.GroupID, userID, 0);
1847
1848 if (landdata.IsGroupOwned && IsGroupMember(landdata.GroupID, userID, (ulong)GroupPowers.AllowRez))
1849 return true;
1485 } 1850 }
1851
1852 return false;
1486 } 1853 }
1487 1854
1488 private bool CanRunConsoleCommand(UUID user, Scene requestFromScene) 1855 private bool CanRunConsoleCommand(UUID user)
1489 { 1856 {
1490 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1857 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1491 if (m_bypassPermissions) return m_bypassPermissionsValue; 1858 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1494,82 +1861,214 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1494 return IsAdministrator(user); 1861 return IsAdministrator(user);
1495 } 1862 }
1496 1863
1497 private bool CanRunScript(UUID script, UUID objectID, UUID user, Scene scene) 1864 private bool CanRunScript(TaskInventoryItem scriptitem, SceneObjectPart part)
1498 { 1865 {
1499 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1866 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1500 if (m_bypassPermissions) return m_bypassPermissionsValue; 1867 if (m_bypassPermissions) return m_bypassPermissionsValue;
1501 1868
1502 return true; 1869 if(scriptitem == null || part == null)
1870 return false;
1871
1872 SceneObjectGroup sog = part.ParentGroup;
1873 if(sog == null)
1874 return false;
1875
1876 Vector3 pos = sog.AbsolutePosition;
1877 ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
1878 if (parcel == null)
1879 return false;
1880
1881 LandData ldata = parcel.LandData;
1882 if(ldata == null)
1883 return false;
1884
1885 uint lflags = ldata.Flags;
1886
1887 if ((lflags & (uint)ParcelFlags.AllowOtherScripts) != 0)
1888 return true;
1889
1890 if ((part.OwnerID == ldata.OwnerID))
1891 return true;
1892
1893 if (((lflags & (uint)ParcelFlags.AllowGroupScripts) != 0)
1894 && (ldata.GroupID != UUID.Zero) && (ldata.GroupID == part.GroupID))
1895 return true;
1896
1897 return GenericEstatePermission(part.OwnerID);
1503 } 1898 }
1504 1899
1505 private bool CanSellParcel(UUID user, ILandObject parcel, Scene scene) 1900 private bool CanSellParcel(UUID user, ILandObject parcel)
1506 { 1901 {
1507 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1902 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1508 if (m_bypassPermissions) return m_bypassPermissionsValue; 1903 if (m_bypassPermissions) return m_bypassPermissionsValue;
1509 1904
1510 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandSetSale, false); 1905 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandSetSale, true);
1511 } 1906 }
1512 1907
1513 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) 1908 private bool CanSellGroupObject(UUID userID, UUID groupID)
1514 { 1909 {
1515 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1910 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1516 if (m_bypassPermissions) return m_bypassPermissionsValue; 1911 if (m_bypassPermissions) return m_bypassPermissionsValue;
1517 1912
1518 return GenericObjectPermission(stealer,objectID, false); 1913 return IsGroupMember(groupID, userID, (ulong)GroupPowers.ObjectSetForSale);
1519 } 1914 }
1520 1915
1521 private bool CanTakeCopyObject(UUID objectID, UUID userID, Scene inScene) 1916 private bool CanSellObjectByUserID(SceneObjectGroup sog, UUID userID, byte saleType)
1522 { 1917 {
1523 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1918 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1524 if (m_bypassPermissions) return m_bypassPermissionsValue; 1919 if (m_bypassPermissions) return m_bypassPermissionsValue;
1525 1920
1526 bool permission = GenericObjectPermission(userID, objectID, false); 1921 if (sog == null || sog.IsDeleted || userID == UUID.Zero)
1922 return false;
1527 1923
1528 SceneObjectGroup so = (SceneObjectGroup)m_scene.Entities[objectID]; 1924 // sell is not a attachment op
1925 if(sog.IsAttachment)
1926 return false;
1529 1927
1530 if (!permission) 1928 if(IsAdministrator(userID))
1531 { 1929 return true;
1532 if (!m_scene.Entities.ContainsKey(objectID))
1533 {
1534 return false;
1535 }
1536 1930
1537 // If it's not an object, we cant edit it. 1931 uint sogEffectiveOwnerPerms = sog.EffectiveOwnerPerms;
1538 if (!(m_scene.Entities[objectID] is SceneObjectGroup)) 1932 if((sogEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1539 { 1933 return false;
1540 return false;
1541 }
1542 1934
1543 // UUID taskOwner = null; 1935 if(saleType == (byte)SaleType.Copy &&
1544 // Added this because at this point in time it wouldn't be wise for 1936 (sogEffectiveOwnerPerms & (uint)PermissionMask.Copy) == 0)
1545 // the administrator object permissions to take effect. 1937 return false;
1546 // UUID objectOwner = task.OwnerID;
1547 1938
1548 if ((so.RootPart.EveryoneMask & PERM_COPY) != 0) 1939 UUID sogOwnerID = sog.OwnerID;
1549 permission = true; 1940
1550 } 1941 if(sogOwnerID == userID)
1942 return true;
1943
1944 // else only group owned can be sold by members with powers
1945 UUID sogGroupID = sog.GroupID;
1946 if(sog.OwnerID != sogGroupID || sogGroupID == UUID.Zero)
1947 return false;
1948
1949 return IsGroupMember(sogGroupID, userID, (ulong)GroupPowers.ObjectSetForSale);
1950 }
1951
1952 private bool CanSellObject(SceneObjectGroup sog, ScenePresence sp, byte saleType)
1953 {
1954 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1955 if (m_bypassPermissions) return m_bypassPermissionsValue;
1551 1956
1552 if (so.OwnerID != userID) 1957 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
1958 return false;
1959
1960 // sell is not a attachment op
1961 if(sog.IsAttachment)
1962 return false;
1963
1964 if(sp.IsGod)
1965 return true;
1966
1967 uint sogEffectiveOwnerPerms = sog.EffectiveOwnerPerms;
1968 if((sogEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
1969 return false;
1970
1971 if(saleType == (byte)SaleType.Copy &&
1972 (sogEffectiveOwnerPerms & (uint)PermissionMask.Copy) == 0)
1973 return false;
1974
1975 UUID userID = sp.UUID;
1976 UUID sogOwnerID = sog.OwnerID;
1977
1978 if(sogOwnerID == userID)
1979 return true;
1980
1981 // else only group owned can be sold by members with powers
1982 UUID sogGroupID = sog.GroupID;
1983 if(sog.OwnerID != sogGroupID || sogGroupID == UUID.Zero)
1984 return false;
1985
1986 ulong powers = 0;
1987 if(!GroupMemberPowers(sogGroupID, sp, ref powers))
1988 return false;
1989
1990 if((powers & (ulong)GroupPowers.ObjectSetForSale) == 0)
1991 return false;
1992
1993 return true;
1994 }
1995
1996 private bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp)
1997 {
1998 // ignore locked, viewers shell ask for confirmation
1999 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2000 if (m_bypassPermissions) return m_bypassPermissionsValue;
2001
2002 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
2003 return false;
2004
2005 // take is not a attachment op
2006 if(sog.IsAttachment)
2007 return false;
2008
2009 UUID sogOwnerID = sog.OwnerID;
2010 UUID spID = sp.UUID;
2011
2012 if(sogOwnerID == spID)
2013 return true;
2014
2015 if (sp.IsGod)
2016 return true;
2017
2018 if((sog.EffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0)
2019 return false;
2020
2021 if (IsFriendWithPerms(sog.UUID, sogOwnerID))
2022 return true;
2023
2024 UUID sogGroupID = sog.GroupID;
2025 if (sogGroupID != UUID.Zero)
1553 { 2026 {
1554 if ((so.GetEffectivePermissions() & (PERM_COPY | PERM_TRANS)) != (PERM_COPY | PERM_TRANS)) 2027 ulong powers = 0;
1555 permission = false; 2028 if(GroupMemberPowers(sogGroupID, sp, ref powers))
2029 {
2030 if(sogGroupID == sogOwnerID)
2031 {
2032 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
2033 return true;
2034 }
2035 return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0;
2036 }
1556 } 2037 }
1557 else 2038 return false;
2039 }
2040
2041 private bool CanTakeCopyObject(SceneObjectGroup sog, ScenePresence sp)
2042 {
2043 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2044 if (m_bypassPermissions) return m_bypassPermissionsValue;
2045
2046 if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted)
2047 return false;
2048
2049 // refuse on attachments
2050 if(sog.IsAttachment && !sp.IsGod)
2051 return false;
2052
2053 uint perms = GetObjectPermissions(sp, sog, true);
2054 if((perms & (uint)PermissionMask.Copy) == 0)
1558 { 2055 {
1559 if ((so.GetEffectivePermissions() & PERM_COPY) != PERM_COPY) 2056 sp.ControllingClient.SendAgentAlertMessage("Copying this item has been denied by the permissions system", false);
1560 permission = false; 2057 return false;
1561 } 2058 }
1562 2059
1563 return permission; 2060 if(sog.OwnerID != sp.UUID && (perms & (uint)PermissionMask.Transfer) == 0)
2061 return false;
2062 return true;
1564 } 2063 }
1565 2064
1566 private bool CanTerraformLand(UUID user, Vector3 position, Scene requestFromScene) 2065 private bool CanTerraformLand(UUID userID, Vector3 position)
1567 { 2066 {
1568 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2067 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1569 if (m_bypassPermissions) return m_bypassPermissionsValue; 2068 if (m_bypassPermissions) return m_bypassPermissionsValue;
1570 2069
1571 // Estate override 2070 // Estate override
1572 if (GenericEstatePermission(user)) 2071 if (GenericEstatePermission(userID))
1573 return true; 2072 return true;
1574 2073
1575 float X = position.X; 2074 float X = position.X;
@@ -1587,13 +2086,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1587 ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y); 2086 ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y);
1588 if (parcel == null) 2087 if (parcel == null)
1589 return false; 2088 return false;
1590 2089
1591 // Others allowed to terraform? 2090 LandData landdata = parcel.LandData;
1592 if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowTerraform)) != 0) 2091 if (landdata == null)
2092 return false;
2093
2094 if ((landdata.Flags & ((int)ParcelFlags.AllowTerraform)) != 0)
1593 return true; 2095 return true;
1594 2096
1595 // Land owner can terraform too 2097 if(landdata.OwnerID == userID)
1596 if (parcel != null && GenericParcelPermission(user, parcel, (ulong)GroupPowers.AllowEditLand)) 2098 return true;
2099
2100 if (landdata.IsGroupOwned && parcel.LandData.GroupID != UUID.Zero &&
2101 IsGroupMember(landdata.GroupID, userID, (ulong)GroupPowers.AllowEditLand))
1597 return true; 2102 return true;
1598 2103
1599 return false; 2104 return false;
@@ -1607,16 +2112,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1607 /// <param name="user"></param> 2112 /// <param name="user"></param>
1608 /// <param name="scene"></param> 2113 /// <param name="scene"></param>
1609 /// <returns></returns> 2114 /// <returns></returns>
1610 private bool CanViewScript(UUID script, UUID objectID, UUID user, Scene scene) 2115 private bool CanViewScript(UUID script, UUID objectID, UUID userID)
1611 { 2116 {
1612 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2117 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1613 if (m_bypassPermissions) return m_bypassPermissionsValue; 2118 if (m_bypassPermissions) return m_bypassPermissionsValue;
1614 2119
2120 // A god is a god is a god
2121 if (IsAdministrator(userID))
2122 return true;
2123
1615 if (objectID == UUID.Zero) // User inventory 2124 if (objectID == UUID.Zero) // User inventory
1616 { 2125 {
1617 IInventoryService invService = m_scene.InventoryService; 2126 IInventoryService invService = m_scene.InventoryService;
1618 InventoryItemBase assetRequestItem = new InventoryItemBase(script, user); 2127 InventoryItemBase assetRequestItem = invService.GetItem(userID, script);
1619 assetRequestItem = invService.GetItem(assetRequestItem);
1620 if (assetRequestItem == null && LibraryRootFolder != null) // Library item 2128 if (assetRequestItem == null && LibraryRootFolder != null) // Library item
1621 { 2129 {
1622 assetRequestItem = LibraryRootFolder.FindItem(script); 2130 assetRequestItem = LibraryRootFolder.FindItem(script);
@@ -1636,60 +2144,53 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1636 // readable only if it's really full perms 2144 // readable only if it's really full perms
1637 // 2145 //
1638 if ((assetRequestItem.CurrentPermissions & 2146 if ((assetRequestItem.CurrentPermissions &
2147/*
1639 ((uint)PermissionMask.Modify | 2148 ((uint)PermissionMask.Modify |
1640 (uint)PermissionMask.Copy | 2149 (uint)PermissionMask.Copy |
1641 (uint)PermissionMask.Transfer)) != 2150 (uint)PermissionMask.Transfer)) !=
1642 ((uint)PermissionMask.Modify | 2151 ((uint)PermissionMask.Modify |
1643 (uint)PermissionMask.Copy | 2152 (uint)PermissionMask.Copy |
1644 (uint)PermissionMask.Transfer)) 2153 (uint)PermissionMask.Transfer))
2154*/
2155 (uint)(PermissionMask.Modify | PermissionMask.Copy)) !=
2156 (uint)(PermissionMask.Modify | PermissionMask.Copy))
1645 return false; 2157 return false;
1646 } 2158 }
1647 else // Prim inventory 2159 else // Prim inventory
1648 { 2160 {
1649 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 2161 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1650
1651 if (part == null) 2162 if (part == null)
1652 return false; 2163 return false;
1653
1654 if (part.OwnerID != user)
1655 {
1656 if (part.GroupID == UUID.Zero)
1657 return false;
1658 2164
1659 if (!IsGroupMember(part.GroupID, user, 0)) 2165 SceneObjectGroup sog = part.ParentGroup;
1660 return false; 2166 if (sog == null)
1661 2167 return false;
1662 if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) 2168
1663 return false; 2169 uint perms = GetObjectPermissions(userID, sog, true);
1664 } 2170 if((perms & (uint)PermissionMask.Modify) == 0)
1665 else 2171 return false;
1666 {
1667 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1668 return false;
1669 }
1670 2172
1671 TaskInventoryItem ti = part.Inventory.GetInventoryItem(script); 2173 TaskInventoryItem ti = part.Inventory.GetInventoryItem(script);
1672 2174
1673 if (ti == null) 2175// if (ti == null || ti.InvType != (int)InventoryType.LSL)
2176 if (ti == null) // legacy may not have type
1674 return false; 2177 return false;
1675 2178
1676 if (ti.OwnerID != user) 2179 uint itperms = GetObjectItemPermissions(userID, ti);
1677 {
1678 if (ti.GroupID == UUID.Zero)
1679 return false;
1680
1681 if (!IsGroupMember(ti.GroupID, user, 0))
1682 return false;
1683 }
1684 2180
1685 // Require full perms 2181 // Require full perms
1686 if ((ti.CurrentPermissions & 2182
1687 ((uint)PermissionMask.Modify | 2183 if ((itperms &
2184/*
2185 ((uint)(PermissionMask.Modify |
1688 (uint)PermissionMask.Copy | 2186 (uint)PermissionMask.Copy |
1689 (uint)PermissionMask.Transfer)) != 2187 (uint)PermissionMask.Transfer)) !=
1690 ((uint)PermissionMask.Modify | 2188 ((uint)PermissionMask.Modify |
1691 (uint)PermissionMask.Copy | 2189 (uint)PermissionMask.Copy |
1692 (uint)PermissionMask.Transfer)) 2190 (uint)PermissionMask.Transfer))
2191*/
2192 (uint)(PermissionMask.Modify | PermissionMask.Copy)) !=
2193 (uint)(PermissionMask.Modify | PermissionMask.Copy))
1693 return false; 2194 return false;
1694 } 2195 }
1695 2196
@@ -1704,16 +2205,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1704 /// <param name="user"></param> 2205 /// <param name="user"></param>
1705 /// <param name="scene"></param> 2206 /// <param name="scene"></param>
1706 /// <returns></returns> 2207 /// <returns></returns>
1707 private bool CanViewNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) 2208 private bool CanViewNotecard(UUID notecard, UUID objectID, UUID userID)
1708 { 2209 {
1709 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2210 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1710 if (m_bypassPermissions) return m_bypassPermissionsValue; 2211 if (m_bypassPermissions) return m_bypassPermissionsValue;
1711 2212
2213 // A god is a god is a god
2214 if (IsAdministrator(userID))
2215 return true;
2216
1712 if (objectID == UUID.Zero) // User inventory 2217 if (objectID == UUID.Zero) // User inventory
1713 { 2218 {
1714 IInventoryService invService = m_scene.InventoryService; 2219 IInventoryService invService = m_scene.InventoryService;
1715 InventoryItemBase assetRequestItem = new InventoryItemBase(notecard, user); 2220 InventoryItemBase assetRequestItem = invService.GetItem(userID, notecard);
1716 assetRequestItem = invService.GetItem(assetRequestItem);
1717 if (assetRequestItem == null && LibraryRootFolder != null) // Library item 2221 if (assetRequestItem == null && LibraryRootFolder != null) // Library item
1718 { 2222 {
1719 assetRequestItem = LibraryRootFolder.FindItem(notecard); 2223 assetRequestItem = LibraryRootFolder.FindItem(notecard);
@@ -1731,40 +2235,29 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1731 } 2235 }
1732 else // Prim inventory 2236 else // Prim inventory
1733 { 2237 {
1734 SceneObjectPart part = scene.GetSceneObjectPart(objectID); 2238 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1735
1736 if (part == null) 2239 if (part == null)
1737 return false; 2240 return false;
1738
1739 if (part.OwnerID != user)
1740 {
1741 if (part.GroupID == UUID.Zero)
1742 return false;
1743
1744 if (!IsGroupMember(part.GroupID, user, 0))
1745 return false;
1746 }
1747 2241
1748 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) 2242 SceneObjectGroup sog = part.ParentGroup;
2243 if (sog == null)
2244 return false;
2245
2246 uint perms = GetObjectPermissions(userID, sog, true);
2247 if((perms & (uint)PermissionMask.Modify) == 0)
1749 return false; 2248 return false;
1750 2249
1751 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); 2250 TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard);
1752 2251
2252// if (ti == null || ti.InvType != (int)InventoryType.Notecard)
1753 if (ti == null) 2253 if (ti == null)
1754 return false; 2254 return false;
1755 2255
1756 if (ti.OwnerID != user) 2256 uint itperms = GetObjectItemPermissions(userID, ti);
1757 {
1758 if (ti.GroupID == UUID.Zero)
1759 return false;
1760
1761 if (!IsGroupMember(ti.GroupID, user, 0))
1762 return false;
1763 }
1764 2257
1765 // Notecards are always readable unless no copy 2258 // Notecards are always readable unless no copy
1766 // 2259 //
1767 if ((ti.CurrentPermissions & 2260 if ((itperms &
1768 (uint)PermissionMask.Copy) != 2261 (uint)PermissionMask.Copy) !=
1769 (uint)PermissionMask.Copy) 2262 (uint)PermissionMask.Copy)
1770 return false; 2263 return false;
@@ -1780,7 +2273,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1780 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2273 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1781 if (m_bypassPermissions) return m_bypassPermissionsValue; 2274 if (m_bypassPermissions) return m_bypassPermissionsValue;
1782 2275
1783 return GenericObjectPermission(userID, objectID, false); 2276 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
2277 if (sog == null)
2278 return false;
2279
2280 uint perms = GetObjectPermissions(userID, sog, true);
2281 if((perms & (uint)PermissionMask.Modify) == 0)
2282 return false;
2283 return true;
1784 } 2284 }
1785 2285
1786 private bool CanDelinkObject(UUID userID, UUID objectID) 2286 private bool CanDelinkObject(UUID userID, UUID objectID)
@@ -1788,10 +2288,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1788 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2288 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1789 if (m_bypassPermissions) return m_bypassPermissionsValue; 2289 if (m_bypassPermissions) return m_bypassPermissionsValue;
1790 2290
1791 return GenericObjectPermission(userID, objectID, false); 2291 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
2292 if (sog == null)
2293 return false;
2294
2295 uint perms = GetObjectPermissions(userID, sog, true);
2296 if((perms & (uint)PermissionMask.Modify) == 0)
2297 return false;
2298 return true;
1792 } 2299 }
1793 2300
1794 private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) 2301 private bool CanBuyLand(UUID userID, ILandObject parcel)
1795 { 2302 {
1796 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2303 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1797 if (m_bypassPermissions) return m_bypassPermissionsValue; 2304 if (m_bypassPermissions) return m_bypassPermissionsValue;
@@ -1804,6 +2311,138 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1804 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2311 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1805 if (m_bypassPermissions) return m_bypassPermissionsValue; 2312 if (m_bypassPermissions) return m_bypassPermissionsValue;
1806 2313
2314 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
2315 if (part == null)
2316 return false;
2317
2318 SceneObjectGroup sog = part.ParentGroup;
2319 if (sog == null)
2320 return false;
2321
2322 if(sog.OwnerID == userID || IsAdministrator(userID))
2323 return true;
2324
2325 if(sog.IsAttachment)
2326 return false;
2327
2328 UUID sogGroupID = sog.GroupID;
2329
2330 if(sogGroupID == UUID.Zero || sogGroupID != sog.OwnerID)
2331 return false;
2332
2333 TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID);
2334 if(ti == null)
2335 return false;
2336
2337 ulong powers = 0;
2338 if(GroupMemberPowers(sogGroupID, userID, ref powers))
2339 {
2340 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
2341 return true;
2342
2343 if((ti.EveryonePermissions & (uint)PermissionMask.Copy) != 0)
2344 return true;
2345 }
2346 return false;
2347 }
2348
2349 // object inventory to object inventory item drag and drop
2350 private bool CanDoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart)
2351 {
2352 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2353
2354 if (sourcePart == null || destPart == null || item == null)
2355 return false;
2356
2357 if (m_bypassPermissions)
2358 return m_bypassPermissionsValue;
2359
2360 SceneObjectGroup srcsog = sourcePart.ParentGroup;
2361 SceneObjectGroup destsog = destPart.ParentGroup;
2362 if (srcsog == null || destsog == null)
2363 return false;
2364
2365 // dest is locked
2366 if((destsog.EffectiveOwnerPerms & (uint)PermissionMask.Move) == 0)
2367 return false;
2368
2369 uint itperms = item.CurrentPermissions;
2370
2371 // if item is no copy the source is modifed
2372 if((itperms & (uint)PermissionMask.Copy) == 0 && (srcsog.EffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0)
2373 return false;
2374
2375 UUID srcOwner = srcsog.OwnerID;
2376 UUID destOwner = destsog.OwnerID;
2377 bool notSameOwner = srcOwner != destOwner;
2378
2379 if(notSameOwner)
2380 {
2381 if((itperms & (uint)PermissionMask.Transfer) == 0)
2382 return false;
2383
2384 // scripts can't be droped
2385 if(item.InvType == (int)InventoryType.LSL)
2386 return false;
2387
2388 if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
2389 return false;
2390 }
2391 else
2392 {
2393 if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0 &&
2394 (destsog.EffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0)
2395 return false;
2396 }
2397
2398 return true;
2399 }
2400
2401 private bool CanDropInObjectInv(InventoryItemBase item, ScenePresence sp, SceneObjectPart destPart)
2402 {
2403 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
2404
2405 if (sp == null || sp.IsDeleted || destPart == null || item == null)
2406 return false;
2407
2408 SceneObjectGroup destsog = destPart.ParentGroup;
2409 if (destsog == null || destsog.IsDeleted)
2410 return false;
2411
2412 if (m_bypassPermissions)
2413 return m_bypassPermissionsValue;
2414
2415 if(sp.IsGod)
2416 return true;
2417
2418 // dest is locked
2419 if((destsog.EffectiveOwnerPerms & (uint)PermissionMask.Move) == 0)
2420 return false;
2421
2422 UUID destOwner = destsog.OwnerID;
2423 UUID spID = sp.UUID;
2424 bool spNotOwner = spID != destOwner;
2425
2426 // scripts can't be droped
2427 if(spNotOwner && item.InvType == (int)InventoryType.LSL)
2428 return false;
2429
2430 if(spNotOwner || item.Owner != destOwner)
2431 {
2432 // no copy item will be moved if it has transfer
2433 uint itperms = item.CurrentPermissions;
2434 if((itperms & (uint)PermissionMask.Transfer) == 0)
2435 return false;
2436 }
2437
2438 // allowdrop is a root part thing and does bypass modify rights
2439 if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
2440 return true;
2441
2442 uint perms = GetObjectPermissions(spID, destsog, true);
2443 if((perms & (uint)PermissionMask.Modify) == 0)
2444 return false;
2445
1807 return true; 2446 return true;
1808 } 2447 }
1809 2448
@@ -1812,6 +2451,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1812 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2451 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1813 if (m_bypassPermissions) return m_bypassPermissionsValue; 2452 if (m_bypassPermissions) return m_bypassPermissionsValue;
1814 2453
2454 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
2455 if (part == null)
2456 return false;
2457
2458 SceneObjectGroup sog = part.ParentGroup;
2459 if (sog == null)
2460 return false;
2461
2462 uint perms = GetObjectPermissions(userID, sog, true);
2463 if((perms & (uint)PermissionMask.Modify) == 0)
2464 return false;
2465
2466 TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID);
2467 if(ti == null)
2468 return false;
2469
2470 //TODO item perm ?
1815 return true; 2471 return true;
1816 } 2472 }
1817 2473
@@ -1828,31 +2484,28 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1828 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2484 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1829 if (m_bypassPermissions) return m_bypassPermissionsValue; 2485 if (m_bypassPermissions) return m_bypassPermissionsValue;
1830 2486
1831 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
1832 ScenePresence p = m_scene.GetScenePresence(userID); 2487 ScenePresence p = m_scene.GetScenePresence(userID);
1833 2488
1834 if (part == null || p == null) 2489 if (p == null)
2490 return false;
2491
2492 SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID);
2493 if (sog == null)
2494 return false;
2495
2496 uint perms = GetObjectPermissions(userID, sog, true);
2497 if((perms & (uint)PermissionMask.Modify) == 0)
1835 return false; 2498 return false;
1836 2499
1837 if (!IsAdministrator(userID)) 2500 if ((int)InventoryType.LSL == invType)
1838 { 2501 {
1839 if (part.OwnerID != userID) 2502 if (m_allowedScriptCreators == UserSet.Administrators)
1840 { 2503 return false;
1841 // Group permissions
1842 if ((part.GroupID == UUID.Zero) || (p.ControllingClient.GetGroupPowers(part.GroupID) == 0) || ((part.GroupMask & (uint)PermissionMask.Modify) == 0))
1843 return false;
1844 } else {
1845 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
1846 return false;
1847 }
1848 if ((int)InventoryType.LSL == invType)
1849 if (m_allowedScriptCreators == UserSet.Administrators)
1850 return false;
1851 } 2504 }
1852 2505
1853 return true; 2506 return true;
1854 } 2507 }
1855 2508
1856 /// <summary> 2509 /// <summary>
1857 /// Check whether the specified user is allowed to create the given inventory type in their inventory. 2510 /// Check whether the specified user is allowed to create the given inventory type in their inventory.
1858 /// </summary> 2511 /// </summary>
@@ -1867,10 +2520,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1867 if ((int)InventoryType.LSL == invType) 2520 if ((int)InventoryType.LSL == invType)
1868 if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID)) 2521 if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID))
1869 return false; 2522 return false;
1870 2523
1871 return true; 2524 return true;
1872 } 2525 }
1873 2526
1874 /// <summary> 2527 /// <summary>
1875 /// Check whether the specified user is allowed to copy the given inventory type in their inventory. 2528 /// Check whether the specified user is allowed to copy the given inventory type in their inventory.
1876 /// </summary> 2529 /// </summary>
@@ -1884,7 +2537,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1884 2537
1885 return true; 2538 return true;
1886 } 2539 }
1887 2540
1888 /// <summary> 2541 /// <summary>
1889 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory. 2542 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
1890 /// </summary> 2543 /// </summary>
@@ -1898,7 +2551,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1898 2551
1899 return true; 2552 return true;
1900 } 2553 }
1901 2554
1902 /// <summary> 2555 /// <summary>
1903 /// Check whether the specified user is allowed to delete the given inventory item from their own inventory. 2556 /// Check whether the specified user is allowed to delete the given inventory item from their own inventory.
1904 /// </summary> 2557 /// </summary>
@@ -1921,22 +2574,22 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1921 return true; 2574 return true;
1922 } 2575 }
1923 2576
1924 private bool CanResetScript(UUID prim, UUID script, UUID agentID, Scene scene) 2577 private bool CanResetScript(UUID primID, UUID script, UUID agentID)
1925 { 2578 {
1926 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 2579 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1927 if (m_bypassPermissions) return m_bypassPermissionsValue; 2580 if (m_bypassPermissions) return m_bypassPermissionsValue;
1928 2581
1929 SceneObjectPart part = m_scene.GetSceneObjectPart(prim); 2582 SceneObjectGroup sog = m_scene.GetGroupByPrim(primID);
1930 2583 if (sog == null)
1931 // If we selected a sub-prim to reset, prim won't represent the object, but only a part. 2584 return false;
1932 // We have to check the permissions of the object, though.
1933 if (part.ParentID != 0) prim = part.ParentUUID;
1934 2585
1935 // You can reset the scripts in any object you can edit 2586 uint perms = GetObjectPermissions(agentID, sog, false);
1936 return GenericObjectPermission(agentID, prim, false); 2587 if((perms & (uint)PermissionMask.Modify) == 0) // ??
2588 return false;
2589 return true;
1937 } 2590 }
1938 2591
1939 private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) 2592 private bool CanCompileScript(UUID ownerUUID, int scriptType)
1940 { 2593 {
1941 //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType); 2594 //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType);
1942 switch (scriptType) { 2595 switch (scriptType) {
@@ -1970,64 +2623,71 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1970 } 2623 }
1971 return(false); 2624 return(false);
1972 } 2625 }
1973 2626
1974 private bool CanControlPrimMedia(UUID agentID, UUID primID, int face) 2627 private bool CanControlPrimMedia(UUID agentID, UUID primID, int face)
1975 { 2628 {
1976// m_log.DebugFormat( 2629// m_log.DebugFormat(
1977// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}", 2630// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}",
1978// agentID, primID, face); 2631// agentID, primID, face);
1979 2632
1980 if (null == MoapModule) 2633 if (null == MoapModule)
1981 return false; 2634 return false;
1982 2635
1983 SceneObjectPart part = m_scene.GetSceneObjectPart(primID); 2636 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
1984 if (null == part) 2637 if (null == part)
1985 return false; 2638 return false;
1986 2639
1987 MediaEntry me = MoapModule.GetMediaEntry(part, face); 2640 MediaEntry me = MoapModule.GetMediaEntry(part, face);
1988 2641
1989 // If there is no existing media entry then it can be controlled (in this context, created). 2642 // If there is no existing media entry then it can be controlled (in this context, created).
1990 if (null == me) 2643 if (null == me)
1991 return true; 2644 return true;
1992 2645
1993// m_log.DebugFormat( 2646// m_log.DebugFormat(
1994// "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}", 2647// "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}",
1995// agentID, primID, face, me.ControlPermissions); 2648// agentID, primID, face, me.ControlPermissions);
1996 2649
1997 return GenericObjectPermission(agentID, part.ParentGroup.UUID, true); 2650 SceneObjectGroup sog = part.ParentGroup;
2651 if (sog == null)
2652 return false;
2653
2654 uint perms = GetObjectPermissions(agentID, sog, false);
2655 if((perms & (uint)PermissionMask.Modify) == 0)
2656 return false;
2657 return true;
1998 } 2658 }
1999 2659
2000 private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face) 2660 private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face)
2001 { 2661 {
2002// m_log.DebugFormat( 2662// m_log.DebugFormat(
2003// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}", 2663// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}",
2004// agentID, primID, face); 2664// agentID, primID, face);
2005 2665
2006 if (null == MoapModule) 2666 if (null == MoapModule)
2007 return false; 2667 return false;
2008 2668
2009 SceneObjectPart part = m_scene.GetSceneObjectPart(primID); 2669 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
2010 if (null == part) 2670 if (null == part)
2011 return false; 2671 return false;
2012 2672
2013 MediaEntry me = MoapModule.GetMediaEntry(part, face); 2673 MediaEntry me = MoapModule.GetMediaEntry(part, face);
2014 2674
2015 // If there is no existing media entry then it can be controlled (in this context, created). 2675 // If there is no existing media entry then it can be controlled (in this context, created).
2016 if (null == me) 2676 if (null == me)
2017 return true; 2677 return true;
2018 2678
2019// m_log.DebugFormat( 2679// m_log.DebugFormat(
2020// "[PERMISSIONS]: Checking CanInteractWithPrimMedia for {0} on {1} face {2} with interact permissions {3}", 2680// "[PERMISSIONS]: Checking CanInteractWithPrimMedia for {0} on {1} face {2} with interact permissions {3}",
2021// agentID, primID, face, me.InteractPermissions); 2681// agentID, primID, face, me.InteractPermissions);
2022 2682
2023 return GenericPrimMediaPermission(part, agentID, me.InteractPermissions); 2683 return GenericPrimMediaPermission(part, agentID, me.InteractPermissions);
2024 } 2684 }
2025 2685
2026 private bool GenericPrimMediaPermission(SceneObjectPart part, UUID agentID, MediaPermission perms) 2686 private bool GenericPrimMediaPermission(SceneObjectPart part, UUID agentID, MediaPermission perms)
2027 { 2687 {
2028// if (IsAdministrator(agentID)) 2688// if (IsAdministrator(agentID))
2029// return true; 2689// return true;
2030 2690
2031 if ((perms & MediaPermission.Anyone) == MediaPermission.Anyone) 2691 if ((perms & MediaPermission.Anyone) == MediaPermission.Anyone)
2032 return true; 2692 return true;
2033 2693
@@ -2036,13 +2696,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions
2036 if (agentID == part.OwnerID) 2696 if (agentID == part.OwnerID)
2037 return true; 2697 return true;
2038 } 2698 }
2039 2699
2040 if ((perms & MediaPermission.Group) == MediaPermission.Group) 2700 if ((perms & MediaPermission.Group) == MediaPermission.Group)
2041 { 2701 {
2042 if (IsGroupMember(part.GroupID, agentID, 0)) 2702 if (IsGroupMember(part.GroupID, agentID, 0))
2043 return true; 2703 return true;
2044 } 2704 }
2045 2705
2046 return false; 2706 return false;
2047 } 2707 }
2048 } 2708 }
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
index bb4dcce..49246a2 100644
--- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using GridRegion = OpenSim.Services.Interfaces.GridRegion;
43 44
44namespace OpenSim.Region.CoreModules.World.Objects.Commands 45namespace OpenSim.Region.CoreModules.World.Objects.Commands
45{ 46{
@@ -53,24 +54,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
53 private ICommandConsole m_console; 54 private ICommandConsole m_console;
54 55
55 public string Name { get { return "Region Commands Module"; } } 56 public string Name { get { return "Region Commands Module"; } }
56 57
57 public Type ReplaceableInterface { get { return null; } } 58 public Type ReplaceableInterface { get { return null; } }
58 59
59 public void Initialise(IConfigSource source) 60 public void Initialise(IConfigSource source)
60 { 61 {
61// m_log.DebugFormat("[REGION COMMANDS MODULE]: INITIALIZED MODULE"); 62// m_log.DebugFormat("[REGION COMMANDS MODULE]: INITIALIZED MODULE");
62 } 63 }
63 64
64 public void PostInitialise() 65 public void PostInitialise()
65 { 66 {
66// m_log.DebugFormat("[REGION COMMANDS MODULE]: POST INITIALIZED MODULE"); 67// m_log.DebugFormat("[REGION COMMANDS MODULE]: POST INITIALIZED MODULE");
67 } 68 }
68 69
69 public void Close() 70 public void Close()
70 { 71 {
71// m_log.DebugFormat("[REGION COMMANDS MODULE]: CLOSED MODULE"); 72// m_log.DebugFormat("[REGION COMMANDS MODULE]: CLOSED MODULE");
72 } 73 }
73 74
74 public void AddRegion(Scene scene) 75 public void AddRegion(Scene scene)
75 { 76 {
76// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); 77// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
@@ -86,14 +87,14 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
86 m_console.Commands.AddCommand( 87 m_console.Commands.AddCommand(
87 "Regions", false, "show region", 88 "Regions", false, "show region",
88 "show region", 89 "show region",
89 "Show control information for the currently selected region (host name, max physical prim size, etc).", 90 "Show control information for the currently selected region (host name, max physical prim size, etc).",
90 "A synonym for \"region get\"", 91 "A synonym for \"region get\"",
91 HandleShowRegion); 92 HandleShowRegion);
92 93
93 m_console.Commands.AddCommand( 94 m_console.Commands.AddCommand(
94 "Regions", false, "region get", 95 "Regions", false, "region get",
95 "region get", 96 "region get",
96 "Show control information for the currently selected region (host name, max physical prim size, etc).", 97 "Show control information for the currently selected region (host name, max physical prim size, etc).",
97 "Some parameters can be set with the \"region set\" command.\n" 98 "Some parameters can be set with the \"region set\" command.\n"
98 + "Others must be changed via a viewer (usually via the region/estate dialog box).", 99 + "Others must be changed via a viewer (usually via the region/estate dialog box).",
99 HandleShowRegion); 100 HandleShowRegion);
@@ -107,6 +108,15 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
107 + "max-agent-limit <int> - Maximum root agent limit. agent-limit cannot exceed this." 108 + "max-agent-limit <int> - Maximum root agent limit. agent-limit cannot exceed this."
108 + " This is not persisted over restart - to set it every time you must add a MaxAgents entry to your regions file.", 109 + " This is not persisted over restart - to set it every time you must add a MaxAgents entry to your regions file.",
109 HandleRegionSet); 110 HandleRegionSet);
111
112 m_console.Commands.AddCommand("Regions", false, "show neighbours",
113 "show neighbours",
114 "Shows the local region neighbours", HandleShowNeighboursCommand);
115
116 m_console.Commands.AddCommand("Regions", false, "show regionsinview",
117 "show regionsinview",
118 "Shows regions that can be seen from a region", HandleShowRegionsInViewCommand);
119
110 } 120 }
111 121
112 public void RemoveRegion(Scene scene) 122 public void RemoveRegion(Scene scene)
@@ -194,7 +204,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
194 { 204 {
195 MainConsole.Instance.OutputFormat("Usage: region set <param> <value>"); 205 MainConsole.Instance.OutputFormat("Usage: region set <param> <value>");
196 return; 206 return;
197 } 207 }
198 208
199 string param = args[2]; 209 string param = args[2];
200 string rawValue = args[3]; 210 string rawValue = args[3];
@@ -215,7 +225,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
215 if (newValue > ri.AgentCapacity) 225 if (newValue > ri.AgentCapacity)
216 { 226 {
217 MainConsole.Instance.OutputFormat( 227 MainConsole.Instance.OutputFormat(
218 "Cannot set {0} to {1} in {2} as max-agent-limit is {3}", "agent-limit", 228 "Cannot set {0} to {1} in {2} as max-agent-limit is {3}", "agent-limit",
219 newValue, m_scene.Name, ri.AgentCapacity); 229 newValue, m_scene.Name, ri.AgentCapacity);
220 } 230 }
221 else 231 else
@@ -271,8 +281,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
271 float totalFrameTime = stats[8]; 281 float totalFrameTime = stats[8];
272// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator 282// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator
273 float physicsFrameTime = stats[10]; 283 float physicsFrameTime = stats[10];
274 float otherFrameTime = stats[11]; 284 float otherFrameTime = stats[12];
275// float imageFrameTime = stats.StatsBlock[12].StatValue; // Ignored 285// float imageFrameTime = stats.StatsBlock[11].StatValue; // Ignored
276 float inPacketsPerSecond = stats[13]; 286 float inPacketsPerSecond = stats[13];
277 float outPacketsPerSecond = stats[14]; 287 float outPacketsPerSecond = stats[14];
278 float unackedBytes = stats[15]; 288 float unackedBytes = stats[15];
@@ -280,7 +290,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
280 float pendingDownloads = stats[17]; 290 float pendingDownloads = stats[17];
281 float pendingUploads = stats[18]; 291 float pendingUploads = stats[18];
282 float activeScripts = stats[19]; 292 float activeScripts = stats[19];
283 float scriptLinesPerSecond = stats[20]; 293 float scriptLinesPerSecond = stats[23];
284 294
285 StringBuilder sb = new StringBuilder(); 295 StringBuilder sb = new StringBuilder();
286 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName); 296 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName);
@@ -309,5 +319,60 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
309 319
310 MainConsole.Instance.Output(sb.ToString()); 320 MainConsole.Instance.Output(sb.ToString());
311 } 321 }
322
323 public void HandleShowNeighboursCommand(string module, string[] cmdparams)
324 {
325 if(m_scene == null)
326 return;
327
328 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
329 return;
330
331 System.Text.StringBuilder caps = new System.Text.StringBuilder();
332
333 RegionInfo sr = m_scene.RegionInfo;
334 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", sr.RegionName, sr.RegionID);
335 List<GridRegion> regions = m_scene.GridService.GetNeighbours(sr.ScopeID, sr.RegionID);
336 foreach (GridRegion r in regions)
337 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
338
339 MainConsole.Instance.Output(caps.ToString());
340 }
341
342 public void HandleShowRegionsInViewCommand(string module, string[] cmdparams)
343 {
344 if(m_scene == null)
345 return;
346
347 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
348 return;
349
350 System.Text.StringBuilder caps = new System.Text.StringBuilder();
351 int maxview = (int)m_scene.MaxRegionViewDistance;
352 RegionInfo sr = m_scene.RegionInfo;
353 caps.AppendFormat("*** Regions that can be seen from {0} ({1}) (MaxRegionViewDistance {2}m) ***\n", sr.RegionName, sr.RegionID, maxview);
354 int startX = (int)sr.WorldLocX;
355 int endX = startX + (int)sr.RegionSizeX;
356 int startY = (int)sr.WorldLocY;
357 int endY = startY + (int)sr.RegionSizeY;
358 startX -= maxview;
359 if(startX < 0 )
360 startX = 0;
361 startY -= maxview;
362 if(startY < 0)
363 startY = 0;
364 endX += maxview;
365 endY += maxview;
366
367 List<GridRegion> regions = m_scene.GridService.GetRegionRange(sr.ScopeID, startX, endX, startY, endY);
368 foreach (GridRegion r in regions)
369 {
370 if(r.RegionHandle == sr.RegionHandle)
371 continue;
372 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
373 }
374
375 MainConsole.Instance.Output(caps.ToString());
376 }
312 } 377 }
313} \ No newline at end of file 378}
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 75a8295..bb3b860 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,30 +59,46 @@ 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;
64 protected bool m_shortCircuitDelays = false;
65 protected bool m_rebootAll = false;
60 66
61 public void Initialise(IConfigSource config) 67 public void Initialise(IConfigSource config)
62 { 68 {
69 IConfig restartConfig = config.Configs["RestartModule"];
70 if (restartConfig != null)
71 {
72 m_MarkerPath = restartConfig.GetString("MarkerPath", String.Empty);
73 }
74 IConfig startupConfig = config.Configs["Startup"];
75 m_shortCircuitDelays = startupConfig.GetBoolean("SkipDelayOnEmptyRegion", false);
76 m_rebootAll = startupConfig.GetBoolean("InworldRestartShutsDown", false);
63 } 77 }
64 78
65 public void AddRegion(Scene scene) 79 public void AddRegion(Scene scene)
66 { 80 {
81 if (m_MarkerPath != String.Empty)
82 File.Delete(Path.Combine(m_MarkerPath,
83 scene.RegionInfo.RegionID.ToString()));
84
67 m_Scene = scene; 85 m_Scene = scene;
68 86
69 scene.RegisterModuleInterface<IRestartModule>(this); 87 scene.RegisterModuleInterface<IRestartModule>(this);
70 MainConsole.Instance.Commands.AddCommand("Regions", 88 MainConsole.Instance.Commands.AddCommand("Regions",
71 false, "region restart bluebox", 89 false, "region restart bluebox",
72 "region restart bluebox <message> <delta seconds>+", 90 "region restart bluebox <message> <delta seconds>+",
73 "Schedule a region restart", 91 "Schedule a region restart",
74 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.", 92 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.",
75 HandleRegionRestart); 93 HandleRegionRestart);
76 94
77 MainConsole.Instance.Commands.AddCommand("Regions", 95 MainConsole.Instance.Commands.AddCommand("Regions",
78 false, "region restart notice", 96 false, "region restart notice",
79 "region restart notice <message> <delta seconds>+", 97 "region restart notice <message> <delta seconds>+",
80 "Schedule a region restart", 98 "Schedule a region restart",
81 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.", 99 "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.",
82 HandleRegionRestart); 100 HandleRegionRestart);
83 101
84 MainConsole.Instance.Commands.AddCommand("Regions", 102 MainConsole.Instance.Commands.AddCommand("Regions",
85 false, "region restart abort", 103 false, "region restart abort",
86 "region restart abort [<message>]", 104 "region restart abort [<message>]",
@@ -118,10 +136,14 @@ namespace OpenSim.Region.CoreModules.World.Region
118 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice) 136 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice)
119 { 137 {
120 if (m_CountdownTimer != null) 138 if (m_CountdownTimer != null)
121 return; 139 {
140 m_CountdownTimer.Stop();
141 m_CountdownTimer = null;
142 }
122 143
123 if (alerts == null) 144 if (alerts == null)
124 { 145 {
146 CreateMarkerFile();
125 m_Scene.RestartNow(); 147 m_Scene.RestartNow();
126 return; 148 return;
127 } 149 }
@@ -129,25 +151,28 @@ namespace OpenSim.Region.CoreModules.World.Region
129 m_Message = message; 151 m_Message = message;
130 m_Initiator = initiator; 152 m_Initiator = initiator;
131 m_Notice = notice; 153 m_Notice = notice;
154 m_CurrentAlerts = alerts;
132 m_Alerts = new List<int>(alerts); 155 m_Alerts = new List<int>(alerts);
133 m_Alerts.Sort(); 156 m_Alerts.Sort();
134 m_Alerts.Reverse(); 157 m_Alerts.Reverse();
135 158
136 if (m_Alerts[0] == 0) 159 if (m_Alerts[0] == 0)
137 { 160 {
161 CreateMarkerFile();
138 m_Scene.RestartNow(); 162 m_Scene.RestartNow();
139 return; 163 return;
140 } 164 }
141 165
142 int nextInterval = DoOneNotice(); 166 int nextInterval = DoOneNotice(true);
143 167
144 SetTimer(nextInterval); 168 SetTimer(nextInterval);
145 } 169 }
146 170
147 public int DoOneNotice() 171 public int DoOneNotice(bool sendOut)
148 { 172 {
149 if (m_Alerts.Count == 0 || m_Alerts[0] == 0) 173 if (m_Alerts.Count == 0 || m_Alerts[0] == 0)
150 { 174 {
175 CreateMarkerFile();
151 m_Scene.RestartNow(); 176 m_Scene.RestartNow();
152 return 0; 177 return 0;
153 } 178 }
@@ -163,39 +188,42 @@ namespace OpenSim.Region.CoreModules.World.Region
163 nextAlert = m_Alerts[1]; 188 nextAlert = m_Alerts[1];
164 break; 189 break;
165 } 190 }
166 191
167 int currentAlert = m_Alerts[0]; 192 int currentAlert = m_Alerts[0];
168 193
169 m_Alerts.RemoveAt(0); 194 m_Alerts.RemoveAt(0);
170 195
171 int minutes = currentAlert / 60; 196 if (sendOut)
172 string currentAlertString = String.Empty;
173 if (minutes > 0)
174 { 197 {
175 if (minutes == 1) 198 int minutes = currentAlert / 60;
176 currentAlertString += "1 minute"; 199 string currentAlertString = String.Empty;
177 else 200 if (minutes > 0)
178 currentAlertString += String.Format("{0} minutes", minutes); 201 {
202 if (minutes == 1)
203 currentAlertString += "1 minute";
204 else
205 currentAlertString += String.Format("{0} minutes", minutes);
206 if ((currentAlert % 60) != 0)
207 currentAlertString += " and ";
208 }
179 if ((currentAlert % 60) != 0) 209 if ((currentAlert % 60) != 0)
180 currentAlertString += " and "; 210 {
181 } 211 int seconds = currentAlert % 60;
182 if ((currentAlert % 60) != 0) 212 if (seconds == 1)
183 { 213 currentAlertString += "1 second";
184 int seconds = currentAlert % 60; 214 else
185 if (seconds == 1) 215 currentAlertString += String.Format("{0} seconds", seconds);
186 currentAlertString += "1 second"; 216 }
187 else
188 currentAlertString += String.Format("{0} seconds", seconds);
189 }
190 217
191 string msg = String.Format(m_Message, currentAlertString); 218 string msg = String.Format(m_Message, currentAlertString);
192 219
193 if (m_DialogModule != null && msg != String.Empty) 220 if (m_DialogModule != null && msg != String.Empty)
194 { 221 {
195 if (m_Notice) 222 if (m_Notice)
196 m_DialogModule.SendGeneralAlert(msg); 223 m_DialogModule.SendGeneralAlert(msg);
197 else 224 else
198 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg); 225 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg);
226 }
199 } 227 }
200 228
201 return currentAlert - nextAlert; 229 return currentAlert - nextAlert;
@@ -219,14 +247,42 @@ namespace OpenSim.Region.CoreModules.World.Region
219 else 247 else
220 { 248 {
221 m_log.WarnFormat( 249 m_log.WarnFormat(
222 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval", 250 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
223 intervalSeconds, m_Scene.Name); 251 intervalSeconds, m_Scene.Name);
224 } 252 }
225 } 253 }
226 254
227 private void OnTimer(object source, ElapsedEventArgs e) 255 private void OnTimer(object source, ElapsedEventArgs e)
228 { 256 {
229 SetTimer(DoOneNotice()); 257 int nextInterval = DoOneNotice(true);
258 if (m_shortCircuitDelays)
259 {
260 if (CountAgents() == 0)
261 {
262 m_Scene.RestartNow();
263 return;
264 }
265 }
266
267 SetTimer(nextInterval);
268 }
269
270 public void DelayRestart(int seconds, string message)
271 {
272 if (m_CountdownTimer == null)
273 return;
274
275 m_CountdownTimer.Stop();
276 m_CountdownTimer = null;
277
278 m_Alerts = new List<int>(m_CurrentAlerts);
279 m_Alerts.Add(seconds);
280 m_Alerts.Sort();
281 m_Alerts.Reverse();
282
283 int nextInterval = DoOneNotice(false);
284
285 SetTimer(nextInterval);
230 } 286 }
231 287
232 public void AbortRestart(string message) 288 public void AbortRestart(string message)
@@ -236,10 +292,14 @@ namespace OpenSim.Region.CoreModules.World.Region
236 m_CountdownTimer.Stop(); 292 m_CountdownTimer.Stop();
237 m_CountdownTimer = null; 293 m_CountdownTimer = null;
238 if (m_DialogModule != null && message != String.Empty) 294 if (m_DialogModule != null && message != String.Empty)
239 m_DialogModule.SendGeneralAlert(message); 295 m_DialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
296 //m_DialogModule.SendGeneralAlert(message);
240 } 297 }
298 if (m_MarkerPath != String.Empty)
299 File.Delete(Path.Combine(m_MarkerPath,
300 m_Scene.RegionInfo.RegionID.ToString()));
241 } 301 }
242 302
243 private void HandleRegionRestart(string module, string[] args) 303 private void HandleRegionRestart(string module, string[] args)
244 { 304 {
245 if (!(MainConsole.Instance.ConsoleScene is Scene)) 305 if (!(MainConsole.Instance.ConsoleScene is Scene))
@@ -282,5 +342,55 @@ namespace OpenSim.Region.CoreModules.World.Region
282 342
283 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 343 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
284 } 344 }
345
346 protected void CreateMarkerFile()
347 {
348 if (m_MarkerPath == String.Empty)
349 return;
350
351 string path = Path.Combine(m_MarkerPath, m_Scene.RegionInfo.RegionID.ToString());
352 try
353 {
354 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
355 FileStream fs = File.Create(path);
356 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
357 Byte[] buf = enc.GetBytes(pidstring);
358 fs.Write(buf, 0, buf.Length);
359 fs.Close();
360 }
361 catch (Exception)
362 {
363 }
364 }
365
366 int CountAgents()
367 {
368 m_log.Info("[RESTART MODULE]: Counting affected avatars");
369 int agents = 0;
370
371 if (m_rebootAll)
372 {
373 foreach (Scene s in SceneManager.Instance.Scenes)
374 {
375 foreach (ScenePresence sp in s.GetScenePresences())
376 {
377 if (!sp.IsChildAgent && !sp.IsNPC)
378 agents++;
379 }
380 }
381 }
382 else
383 {
384 foreach (ScenePresence sp in m_Scene.GetScenePresences())
385 {
386 if (!sp.IsChildAgent && !sp.IsNPC)
387 agents++;
388 }
389 }
390
391 m_log.InfoFormat("[RESTART MODULE]: Avatars in region: {0}", agents);
392
393 return agents;
394 }
285 } 395 }
286} \ No newline at end of file 396}
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs
index 65f464a..52a80d6 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
69 MemoryStream stream = new MemoryStream(); 69 MemoryStream stream = new MemoryStream();
70 XmlTextWriter formatter = new XmlTextWriter(stream, Encoding.UTF8); 70 XmlTextWriter formatter = new XmlTextWriter(stream, Encoding.UTF8);
71 XmlDocument doc = new XmlDocument(); 71 XmlDocument doc = new XmlDocument();
72 72 doc.XmlResolver=null;
73 doc.LoadXml(xmlstream); 73 doc.LoadXml(xmlstream);
74 formatter.Formatting = Formatting.Indented; 74 formatter.Formatting = Formatting.Indented;
75 doc.WriteContentTo(formatter); 75 doc.WriteContentTo(formatter);
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
index e0247d9..c9bc335 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SerialiserModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SerialiserModule")]
46 public class SerialiserModule : ISharedRegionModule, IRegionSerialiserModule 46 public class SerialiserModule : ISharedRegionModule, IRegionSerialiserModule
47 { 47 {
48 private static readonly ILog m_log = 48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51// private Commander m_commander = new Commander("export"); 51// private Commander m_commander = new Commander("export");
@@ -55,15 +55,15 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
55 55
56 #region ISharedRegionModule Members 56 #region ISharedRegionModule Members
57 57
58 public Type ReplaceableInterface 58 public Type ReplaceableInterface
59 { 59 {
60 get { return null; } 60 get { return null; }
61 } 61 }
62 62
63 public void Initialise(IConfigSource source) 63 public void Initialise(IConfigSource source)
64 { 64 {
65 IConfig config = source.Configs["Serialiser"]; 65 IConfig config = source.Configs["Serialiser"];
66 if (config != null) 66 if (config != null)
67 { 67 {
68 m_savedir = config.GetString("save_dir", m_savedir); 68 m_savedir = config.GetString("save_dir", m_savedir);
69 } 69 }
@@ -150,7 +150,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser
150 { 150 {
151 SceneXmlLoader.SavePrimsToXml2(scene, stream, min, max); 151 SceneXmlLoader.SavePrimsToXml2(scene, stream, min, max);
152 } 152 }
153 153
154 public void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName) 154 public void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName)
155 { 155 {
156 SceneXmlLoader.SaveNamedPrimsToXml2(scene, primName, fileName); 156 SceneXmlLoader.SaveNamedPrimsToXml2(scene, primName, fileName);
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index a5bb1a7..23475a1 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
43 [TestFixture] 43 [TestFixture]
44 public class SerialiserTests : OpenSimTestCase 44 public class SerialiserTests : OpenSimTestCase
45 { 45 {
46 private const string ObjectRootPartStubXml = 46 private const string ObjectRootPartStubXml =
47@"<SceneObjectGroup> 47@"<SceneObjectGroup>
48 <RootPart> 48 <RootPart>
49 <SceneObjectPart xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""> 49 <SceneObjectPart xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
@@ -149,9 +149,9 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
149 <llsd> 149 <llsd>
150 <map> 150 <map>
151 <key>MyNamespace</key> 151 <key>MyNamespace</key>
152 <map> 152 <map>
153 <key>MyStore</key> 153 <key>MyStore</key>
154 <map> 154 <map>
155 <key>the answer</key> 155 <key>the answer</key>
156 <integer>42</integer> 156 <integer>42</integer>
157 </map> 157 </map>
@@ -162,12 +162,12 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
162 </SceneObjectPart> 162 </SceneObjectPart>
163 </RootPart>"; 163 </RootPart>";
164 164
165 private const string ObjectWithNoOtherPartsXml = ObjectRootPartStubXml + 165 private const string ObjectWithNoOtherPartsXml = ObjectRootPartStubXml +
166@" 166@"
167 <OtherParts /> 167 <OtherParts />
168</SceneObjectGroup>"; 168</SceneObjectGroup>";
169 169
170 private const string ObjectWithOtherPartsXml = ObjectRootPartStubXml + 170 private const string ObjectWithOtherPartsXml = ObjectRootPartStubXml +
171@" 171@"
172 <OtherParts> 172 <OtherParts>
173 <Part> 173 <Part>
@@ -574,9 +574,9 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
574 <llsd> 574 <llsd>
575 <map> 575 <map>
576 <key>MyNamespace</key> 576 <key>MyNamespace</key>
577 <map> 577 <map>
578 <key>MyStore</key> 578 <key>MyStore</key>
579 <map> 579 <map>
580 <key>last words</key> 580 <key>last words</key>
581 <string>Rosebud</string> 581 <string>Rosebud</string>
582 </map> 582 </map>
@@ -636,7 +636,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
636 Assert.That(part.Name, Is.EqualTo("PrimMyRide")); 636 Assert.That(part.Name, Is.EqualTo("PrimMyRide"));
637 OSDMap store = part.DynAttrs.GetStore("MyNamespace", "MyStore"); 637 OSDMap store = part.DynAttrs.GetStore("MyNamespace", "MyStore");
638 Assert.AreEqual(42, store["the answer"].AsInteger()); 638 Assert.AreEqual(42, store["the answer"].AsInteger());
639 } 639 }
640 640
641 { 641 {
642 SceneObjectPart part = parts[1]; 642 SceneObjectPart part = parts[1];
@@ -720,10 +720,12 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
720 string xml = SceneObjectSerializer.ToOriginalXmlFormat(so); 720 string xml = SceneObjectSerializer.ToOriginalXmlFormat(so);
721 721
722 XmlTextReader xtr = new XmlTextReader(new StringReader(xml)); 722 XmlTextReader xtr = new XmlTextReader(new StringReader(xml));
723 xtr.ProhibitDtd = true;
724
723 xtr.ReadStartElement("SceneObjectGroup"); 725 xtr.ReadStartElement("SceneObjectGroup");
724 xtr.ReadStartElement("RootPart"); 726 xtr.ReadStartElement("RootPart");
725 xtr.ReadStartElement("SceneObjectPart"); 727 xtr.ReadStartElement("SceneObjectPart");
726 728
727 UUID uuid = UUID.Zero; 729 UUID uuid = UUID.Zero;
728 string name = null; 730 string name = null;
729 UUID creatorId = UUID.Zero; 731 UUID creatorId = UUID.Zero;
@@ -733,7 +735,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
733 { 735 {
734 if (xtr.NodeType != XmlNodeType.Element) 736 if (xtr.NodeType != XmlNodeType.Element)
735 continue; 737 continue;
736 738
737 switch (xtr.Name) 739 switch (xtr.Name)
738 { 740 {
739 case "UUID": 741 case "UUID":
@@ -831,9 +833,11 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
831 string xml2 = m_serialiserModule.SerializeGroupToXml2(so, options); 833 string xml2 = m_serialiserModule.SerializeGroupToXml2(so, options);
832 834
833 XmlTextReader xtr = new XmlTextReader(new StringReader(xml2)); 835 XmlTextReader xtr = new XmlTextReader(new StringReader(xml2));
836 xtr.ProhibitDtd = true;
837
834 xtr.ReadStartElement("SceneObjectGroup"); 838 xtr.ReadStartElement("SceneObjectGroup");
835 xtr.ReadStartElement("SceneObjectPart"); 839 xtr.ReadStartElement("SceneObjectPart");
836 840
837 UUID uuid = UUID.Zero; 841 UUID uuid = UUID.Zero;
838 string name = null; 842 string name = null;
839 UUID creatorId = UUID.Zero; 843 UUID creatorId = UUID.Zero;
@@ -843,7 +847,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
843 { 847 {
844 if (xtr.NodeType != XmlNodeType.Element) 848 if (xtr.NodeType != XmlNodeType.Element)
845 continue; 849 continue;
846 850
847 switch (xtr.Name) 851 switch (xtr.Name)
848 { 852 {
849 case "UUID": 853 case "UUID":
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index d093224..2b7db18 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 (grp.HasPrivateAttachmentPoint)
134 { 149 {
135 if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID) 150 ssp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
136 return; 151 ownerID, (float)gain, flags);
137 152 return;
138 if (sp.ControllingClient.AgentId == grp.OwnerID)
139 dis = 0;
140 } 153 }
141 154
142 // Scale by distance 155 if (!ssp.ParcelAllowThisAvatarSounds)
143 double thisSpGain = gain * ((radius - dis) / radius); 156 return;
157 }
144 158
159 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
160 {
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,35 @@ 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/* mantis 7942: coment out to allow trigger in HUDs to send sounds to all
191 if (grp.HasPrivateAttachmentPoint)
192 {
193 ssp.ControllingClient.SendTriggeredSound(soundId, ownerID,
194 objectID, parentID, handle, position,
195 (float)gain);
196 return;
197 }
198*/
168 } 199 }
169 } 200 }
170 201
@@ -174,16 +205,12 @@ namespace OpenSim.Region.CoreModules.World.Sound
174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 205 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
175 { 206 {
176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 207 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
177 208 if (dis > radius) // Max audio distance
178 if (dis > MaxDistance) // Max audio distance
179 return; 209 return;
180 210
181 // Scale by distance
182 double thisSpGain = gain * ((radius - dis) / radius);
183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID, 211 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position, 212 objectID, parentID, handle, position,
186 (float)thisSpGain); 213 (float)gain);
187 }); 214 });
188 } 215 }
189 216
@@ -198,40 +225,13 @@ namespace OpenSim.Region.CoreModules.World.Sound
198 225
199 private static void StopSound(SceneObjectPart m_host) 226 private static void StopSound(SceneObjectPart m_host)
200 { 227 {
201 m_host.AdjustSoundGain(0); 228// m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead 229 m_host.Sound = UUID.Zero;
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 230 m_host.SoundFlags = (byte)SoundFlags.STOP;
204 { 231 m_host.SoundRadius = 0;
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 232 m_host.SoundGain = 0;
206 { 233 m_host.ScheduleFullUpdate();
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) 234 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 } 235 }
236 236
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) 237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
248 248
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 { 250 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) 251 if (Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) < radius)
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); 252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 }); 253 });
254 } 254 }
@@ -262,21 +262,24 @@ namespace OpenSim.Region.CoreModules.World.Sound
262 // 20080530 Updated to remove code duplication 262 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work 263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID, 264 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster) 265 double volume, double radius, bool isMaster, bool isSlave)
266 { 266 {
267 SceneObjectPart m_host; 267 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) 268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return; 269 return;
270 270
271 byte iflags = 1; // looping
271 if (isMaster) 272 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 273 iflags |= (byte)SoundFlags.SYNC_MASTER;
273 274 // TODO check viewer seems to accept both
274 if (m_host.Sound != UUID.Zero) 275 if (isSlave)
275 StopSound(m_host); 276 iflags |= (byte)SoundFlags.SYNC_SLAVE;
277 if (m_host.SoundQueueing)
278 iflags |= (byte)SoundFlags.QUEUE;
276 279
277 m_host.Sound = soundID; 280 m_host.Sound = soundID;
278 m_host.SoundGain = volume; 281 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping 282 m_host.SoundFlags = iflags;
280 m_host.SoundRadius = radius; 283 m_host.SoundRadius = radius;
281 284
282 m_host.ScheduleFullUpdate(); 285 m_host.ScheduleFullUpdate();
@@ -301,41 +304,18 @@ namespace OpenSim.Region.CoreModules.World.Sound
301 Vector3 position = part.AbsolutePosition; // region local 304 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle; 305 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303 306
304 if (useMaster) 307 if(triggered)
305 { 308 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 309 else
334 { 310 {
335 if (triggered) 311 byte bflags = 0;
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); 312
337 else 313 if (isMaster)
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); 314 bflags |= (byte)SoundFlags.SYNC_MASTER;
315 // TODO check viewer seems to accept both
316 if (useMaster)
317 bflags |= (byte)SoundFlags.SYNC_SLAVE;
318 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, bflags, radius);
339 } 319 }
340 } 320 }
341 321
diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
index d0318eb..e2b3487 100644
--- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
@@ -77,7 +77,7 @@ namespace OpenSim.Region.CoreModules
77 // Number of virtual days to a virtual year 77 // Number of virtual days to a virtual year
78 private int m_YearLengthDays = 0; 78 private int m_YearLengthDays = 0;
79 79
80 // Ratio of Daylight hours to Night time hours. This is accomplished by shifting the 80 // Ratio of Daylight hours to Night time hours. This is accomplished by shifting the
81 // sun's orbit above the horizon 81 // sun's orbit above the horizon
82 private double m_HorizonShift = 0; 82 private double m_HorizonShift = 0;
83 83
@@ -162,7 +162,7 @@ namespace OpenSim.Region.CoreModules
162 // Determine the current "day" from current time, so we can use "today" 162 // Determine the current "day" from current time, so we can use "today"
163 // to determine Seasonal Tilt and what'not 163 // to determine Seasonal Tilt and what'not
164 164
165 // Integer math rounded is on purpose to drop fractional day, determines number 165 // Integer math rounded is on purpose to drop fractional day, determines number
166 // of virtual days since Epoch 166 // of virtual days since Epoch
167 PosTime = CurrentTime / SecondsPerSunCycle; 167 PosTime = CurrentTime / SecondsPerSunCycle;
168 168
@@ -343,7 +343,7 @@ namespace OpenSim.Region.CoreModules
343 m_log.Debug("[SUN]: Positional data updated every " + m_UpdateInterval + " frames"); 343 m_log.Debug("[SUN]: Positional data updated every " + m_UpdateInterval + " frames");
344 } 344 }
345 345
346 public Type ReplaceableInterface 346 public Type ReplaceableInterface
347 { 347 {
348 get { return null; } 348 get { return null; }
349 } 349 }
@@ -417,7 +417,7 @@ namespace OpenSim.Region.CoreModules
417 client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); 417 client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
418 } 418 }
419 } 419 }
420 } 420 }
421 421
422 public void SunUpdate() 422 public void SunUpdate()
423 { 423 {
@@ -464,7 +464,7 @@ namespace OpenSim.Region.CoreModules
464 464
465 while (sunFixedHour < 0) 465 while (sunFixedHour < 0)
466 sunFixedHour += 24; 466 sunFixedHour += 24;
467 467
468 m_SunFixedHour = sunFixedHour; 468 m_SunFixedHour = sunFixedHour;
469 m_SunFixed = fixedSun; 469 m_SunFixed = fixedSun;
470 470
@@ -516,7 +516,7 @@ namespace OpenSim.Region.CoreModules
516 516
517 case "current_time": 517 case "current_time":
518 return GetCurrentTimeAsLindenSunHour(); 518 return GetCurrentTimeAsLindenSunHour();
519 519
520 default: 520 default:
521 throw new Exception("Unknown sun parameter."); 521 throw new Exception("Unknown sun parameter.");
522 } 522 }
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/BMP.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs
index fb57c82..ec2d085 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs
@@ -47,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
47 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
48 public override void SaveFile(string filename, ITerrainChannel map) 48 public override void SaveFile(string filename, ITerrainChannel map)
49 { 49 {
50 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
51 51 colours.Save(filename,ImageFormat.Bmp);
52 colours.Save(filename, ImageFormat.Bmp);
53 } 52 }
54 53
55 /// <summary> 54 /// <summary>
@@ -59,9 +58,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 /// <param name="map">The terrain channel being saved</param> 58 /// <param name="map">The terrain channel being saved</param>
60 public override void SaveStream(Stream stream, ITerrainChannel map) 59 public override void SaveStream(Stream stream, ITerrainChannel map)
61 { 60 {
62 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 61 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
63 62 colours.Save(stream,ImageFormat.Bmp);
64 colours.Save(stream, ImageFormat.Png);
65 } 63 }
66 64
67 /// <summary> 65 /// <summary>
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs
index 79cc50b..3843708 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs
@@ -36,9 +36,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
36 { 36 {
37 public override void SaveFile(string filename, ITerrainChannel map) 37 public override void SaveFile(string filename, ITerrainChannel map)
38 { 38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 39 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
40 40 colours.Save(filename,ImageFormat.Gif);
41 colours.Save(filename, ImageFormat.Gif);
42 } 41 }
43 42
44 /// <summary> 43 /// <summary>
@@ -48,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
48 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map) 48 public override void SaveStream(Stream stream, ITerrainChannel map)
50 { 49 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
52 51 colours.Save(stream,ImageFormat.Gif);
53 colours.Save(stream, ImageFormat.Gif);
54 } 52 }
55 53
56 public override string ToString() 54 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d5c77ec..bcd9dcd 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 /// <returns>A terrain channel generated from the image.</returns> 59 /// <returns>A terrain channel generated from the image.</returns>
60 public virtual ITerrainChannel LoadFile(string filename) 60 public virtual ITerrainChannel LoadFile(string filename)
61 { 61 {
62 using (Bitmap b = new Bitmap(filename)) 62 using(Bitmap b = new Bitmap(filename))
63 return LoadBitmap(b); 63 return LoadBitmap(b);
64 } 64 }
65 65
@@ -111,9 +111,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
111 /// <param name="map">The terrain channel being saved</param> 111 /// <param name="map">The terrain channel being saved</param>
112 public virtual void SaveFile(string filename, ITerrainChannel map) 112 public virtual void SaveFile(string filename, ITerrainChannel map)
113 { 113 {
114 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 114 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
115 115 colours.Save(filename,ImageFormat.Png);
116 colours.Save(filename, ImageFormat.Png);
117 } 116 }
118 117
119 /// <summary> 118 /// <summary>
@@ -123,12 +122,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
123 /// <param name="map">The terrain channel being saved</param> 122 /// <param name="map">The terrain channel being saved</param>
124 public virtual void SaveStream(Stream stream, ITerrainChannel map) 123 public virtual void SaveStream(Stream stream, ITerrainChannel map)
125 { 124 {
126 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 125 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
127 126 colours.Save(stream,ImageFormat.Png);
128 colours.Save(stream, ImageFormat.Png);
129 } 127 }
130 128
131 public virtual void SaveFile(ITerrainChannel m_channel, string filename, 129 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
132 int offsetX, int offsetY, 130 int offsetX, int offsetY,
133 int fileWidth, int fileHeight, 131 int fileWidth, int fileHeight,
134 int regionSizeX, int regionSizeY) 132 int regionSizeX, int regionSizeY)
@@ -162,13 +160,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
162 { 160 {
163 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY); 161 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
164 } 162 }
165 163
166 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel); 164 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel);
167 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY); 165 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY);
168 for (int x = 0; x < regionSizeX; x++) 166 for (int x = 0; x < regionSizeX; x++)
169 for (int y = 0; y < regionSizeY; y++) 167 for (int y = 0; y < regionSizeY; y++)
170 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y)); 168 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y));
171 169
172 Save(newBitmap, filename); 170 Save(newBitmap, filename);
173 } 171 }
174 finally 172 finally
@@ -213,8 +211,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
213 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns> 211 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns>
214 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) 212 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map)
215 { 213 {
214 // Bitmap bmp = new Bitmap(map.Width, map.Height, PixelFormat.Format24bppRgb);
216 Bitmap bmp = new Bitmap(map.Width, map.Height); 215 Bitmap bmp = new Bitmap(map.Width, map.Height);
217 216
217
218 const int pallete = 256; 218 const int pallete = 256;
219 219
220 Color[] grays = new Color[pallete]; 220 Color[] grays = new Color[pallete];
@@ -227,59 +227,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
227 { 227 {
228 for (int x = 0; x < map.Width; x++) 228 for (int x = 0; x < map.Width; x++)
229 { 229 {
230 // 512 is the largest possible height before colours clamp 230 // 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 231
255 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png")) 232 // int colorindex = (int)map[x, y]; // one to one conversion 0 - 255m range
256 { 233 // 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 234
268 for (int y = 0; y < map.Height; y++) 235 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 236
275 // Handle error conditions 237 // clamp it not adding the red warning
276 if (colorindex > pallete - 1 || colorindex < 0) 238 if (colorindex < 0)
277 bmp.SetPixel(x, map.Height - y - 1, Color.Red); 239 colorindex = 0;
278 else 240 else if (colorindex >= pallete)
279 bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); 241 colorindex = pallete - 1;
242 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
280 } 243 }
281 } 244 }
282 return bmp; 245 return bmp;
283 } 246 }
284 } 247 }
285} 248}
249
250
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
index 9cc767a..d604dc7 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs
@@ -59,9 +59,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
59 59
60 public void SaveFile(string filename, ITerrainChannel map) 60 public void SaveFile(string filename, ITerrainChannel map)
61 { 61 {
62 Bitmap colours = CreateBitmapFromMap(map); 62 using(Bitmap colours = CreateBitmapFromMap(map))
63 63 colours.Save(filename,ImageFormat.Jpeg);
64 colours.Save(filename, ImageFormat.Jpeg);
65 } 64 }
66 65
67 /// <summary> 66 /// <summary>
@@ -71,9 +70,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
71 /// <param name="map">The terrain channel being saved</param> 70 /// <param name="map">The terrain channel being saved</param>
72 public void SaveStream(Stream stream, ITerrainChannel map) 71 public void SaveStream(Stream stream, ITerrainChannel map)
73 { 72 {
74 Bitmap colours = CreateBitmapFromMap(map); 73 using(Bitmap colours = CreateBitmapFromMap(map))
75 74 colours.Save(stream,ImageFormat.Jpeg);
76 colours.Save(stream, ImageFormat.Jpeg);
77 } 75 }
78 76
79 public virtual void SaveFile(ITerrainChannel m_channel, string filename, 77 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
@@ -106,10 +104,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
106 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png")) 104 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png"))
107 { 105 {
108 pallete = gradientmapLd.Height; 106 pallete = gradientmapLd.Height;
109 107
110 bmp = new Bitmap(map.Width, map.Height); 108 bmp = new Bitmap(map.Width, map.Height);
111 colours = new Color[pallete]; 109 colours = new Color[pallete];
112 110
113 for (int i = 0; i < pallete; i++) 111 for (int i = 0; i < pallete; i++)
114 { 112 {
115 colours[i] = gradientmapLd.GetPixel(0, i); 113 colours[i] = gradientmapLd.GetPixel(0, i);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
index be1fb24..68d6ed2 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
@@ -267,6 +275,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
267 public bool SupportsTileSave() 275 public bool SupportsTileSave()
268 { 276 {
269 return false; 277 return false;
270 } 278 }
271 } 279 }
272} \ No newline at end of file 280} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs
index c5c12ae..8ea8e9d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs
@@ -36,9 +36,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
36 { 36 {
37 public override void SaveFile(string filename, ITerrainChannel map) 37 public override void SaveFile(string filename, ITerrainChannel map)
38 { 38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 39 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
40 40 colours.Save(filename,ImageFormat.Png);
41 colours.Save(filename, ImageFormat.Png);
42 } 41 }
43 42
44 /// <summary> 43 /// <summary>
@@ -48,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
48 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map) 48 public override void SaveStream(Stream stream, ITerrainChannel map)
50 { 49 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
52 51 colours.Save(stream,ImageFormat.Png);
53 colours.Save(stream, ImageFormat.Png);
54 } 52 }
55 53
56 public override string ToString() 54 public override string ToString()
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
index b416b82..d103a6f 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs
@@ -36,9 +36,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
36 { 36 {
37 public override void SaveFile(string filename, ITerrainChannel map) 37 public override void SaveFile(string filename, ITerrainChannel map)
38 { 38 {
39 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 39 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
40 40 colours.Save(filename,ImageFormat.Tiff);
41 colours.Save(filename, ImageFormat.Tiff);
42 } 41 }
43 42
44 /// <summary> 43 /// <summary>
@@ -48,9 +47,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
48 /// <param name="map">The terrain channel being saved</param> 47 /// <param name="map">The terrain channel being saved</param>
49 public override void SaveStream(Stream stream, ITerrainChannel map) 48 public override void SaveStream(Stream stream, ITerrainChannel map)
50 { 49 {
51 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 50 using(Bitmap colours = CreateGrayscaleBitmapFromMap(map))
52 51 colours.Save(stream,ImageFormat.Tiff);
53 colours.Save(stream, ImageFormat.Tiff);
54 } 52 }
55 53
56 public override string ToString() 54 public override string ToString()
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..f7be25f 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/ITerrainLoader.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
index 3ba3657..855d131 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
33 public interface ITerrainLoader 33 public interface ITerrainLoader
34 { 34 {
35 // Returns true if that extension can be used for terrain save-tile 35 // Returns true if that extension can be used for terrain save-tile
36 // (Look into each file in Region.CoreModules.World.Terrain.FileLoaders) 36 // (Look into each file in Region.CoreModules.World.Terrain.FileLoaders)
37 bool SupportsTileSave(); 37 bool SupportsTileSave();
38 38
39 string FileExtension { get; } 39 string FileExtension { get; }
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..9d3d4cb 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;
@@ -76,7 +77,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
76 { 77 {
77 map[x, y] += delta; 78 map[x, y] += delta;
78 } 79 }
79 80
80 } 81 }
81 } 82 }
82 } 83 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
index 68145f2..a88a022 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
@@ -74,7 +58,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
74 map[x, y] = 0.0; 58 map[x, y] = 0.0;
75 else 59 else
76 map[x, y] = newz; 60 map[x, y] = newz;
77 } 61 }
78 } 62 }
79 } 63 }
80 64
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..5305cb4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
@@ -33,40 +33,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
33 public class RaiseSphere : ITerrainPaintableEffect 33 public class RaiseSphere : ITerrainPaintableEffect
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36
37 36
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37
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
48 if (xFrom < 0)
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 44
60 for (x = xFrom; x < xTo; x++) 45 for (x = startX; x <= endX; 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..ca30e9e 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
@@ -41,23 +41,23 @@ 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
48 49
49 if (duration > 1.0) 50 if (duration > 1.0)
50 duration = 1.0; 51 duration = 1.0;
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..0342962 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
@@ -34,23 +34,27 @@ 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
41 int x, y; 42 int x, y;
42 double[,] tweak = new double[map.Width,map.Height]; 43 double[,] tweak = new double[map.Width,map.Height];
43 44
44 double area = strength; 45 double area = strength;
45 double step = strength / 4.0; 46 double step = strength / 4.0;
46 duration = 0.03; //MCP Should be read from ini file 47 duration = 0.03; //MCP Should be read from ini file
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..6df0075 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
@@ -221,26 +231,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain
221 // Install terrain module in the simulator 231 // Install terrain module in the simulator
222 lock(m_scene) 232 lock(m_scene)
223 { 233 {
234 if(m_scene.Bakedmap != null)
235 {
236 m_baked = m_scene.Bakedmap;
237 }
224 if (m_scene.Heightmap == null) 238 if (m_scene.Heightmap == null)
225 { 239 {
226 m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX, 240 if(m_baked != null)
227 (int)m_scene.RegionInfo.RegionSizeY, 241 m_channel = m_baked.MakeCopy();
228 (int)m_scene.RegionInfo.RegionSizeZ); 242 else
243 m_channel = new TerrainChannel(m_InitialTerrain,
244 (int)m_scene.RegionInfo.RegionSizeX,
245 (int)m_scene.RegionInfo.RegionSizeY,
246 (int)m_scene.RegionInfo.RegionSizeZ);
229 m_scene.Heightmap = m_channel; 247 m_scene.Heightmap = m_channel;
230 UpdateRevertMap();
231 } 248 }
232 else 249 else
233 { 250 {
234 m_channel = m_scene.Heightmap; 251 m_channel = m_scene.Heightmap;
235 UpdateRevertMap();
236 } 252 }
253 if(m_baked == null)
254 UpdateBakedMap();
237 255
238 m_scene.RegisterModuleInterface<ITerrainModule>(this); 256 m_scene.RegisterModuleInterface<ITerrainModule>(this);
239 m_scene.EventManager.OnNewClient += EventManager_OnNewClient; 257 m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
240 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed; 258 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
241 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 259 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
242 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; 260 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
243 m_scene.EventManager.OnFrame += EventManager_OnFrame; 261 m_scene.EventManager.OnTerrainCheckUpdates += EventManager_TerrainCheckUpdates;
244 } 262 }
245 263
246 InstallDefaultEffects(); 264 InstallDefaultEffects();
@@ -279,7 +297,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
279 // remove the commands 297 // remove the commands
280 m_scene.UnregisterModuleCommander(m_commander.Name); 298 m_scene.UnregisterModuleCommander(m_commander.Name);
281 // remove the event-handlers 299 // remove the event-handlers
282 m_scene.EventManager.OnFrame -= EventManager_OnFrame; 300
301 m_scene.EventManager.OnTerrainCheckUpdates -= EventManager_TerrainCheckUpdates;
283 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick; 302 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick;
284 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; 303 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
285 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed; 304 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
@@ -334,7 +353,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
334 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); 353 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
335 m_scene.Heightmap = channel; 354 m_scene.Heightmap = channel;
336 m_channel = channel; 355 m_channel = channel;
337 UpdateRevertMap(); 356 UpdateBakedMap();
338 } 357 }
339 catch(NotImplementedException) 358 catch(NotImplementedException)
340 { 359 {
@@ -426,7 +445,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
426 { 445 {
427 ITerrainChannel channel = loader.Value.LoadStream(stream); 446 ITerrainChannel channel = loader.Value.LoadStream(stream);
428 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); 447 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
429 UpdateRevertMap(); 448 UpdateBakedMap();
430 } 449 }
431 catch(NotImplementedException) 450 catch(NotImplementedException)
432 { 451 {
@@ -444,6 +463,37 @@ namespace OpenSim.Region.CoreModules.World.Terrain
444 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); 463 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
445 } 464 }
446 465
466 public void LoadFromStream(string filename, Vector3 displacement,
467 float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize, Stream stream)
468 {
469 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
470 {
471 if (filename.EndsWith(loader.Key))
472 {
473 lock (m_scene)
474 {
475 try
476 {
477 ITerrainChannel channel = loader.Value.LoadStream(stream);
478 m_channel.MergeWithBounding(channel, displacement, rotationDegrees, boundingOrigin, boundingSize);
479 UpdateBakedMap();
480 }
481 catch (NotImplementedException)
482 {
483 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
484 " parser does not support file loading. (May be save only)");
485 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value));
486 }
487 }
488
489 m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully");
490 return;
491 }
492 }
493 m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format.");
494 throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename));
495 }
496
447 private static Stream URIFetch(Uri uri) 497 private static Stream URIFetch(Uri uri)
448 { 498 {
449 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 499 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
@@ -506,12 +556,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
506 556
507 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. 557 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
508 // ITerrainModule.TaintTerrain() 558 // ITerrainModule.TaintTerrain()
509 public void TaintTerrain() 559 public void TaintTerrain ()
510 { 560 {
511 lock(m_perClientPatchUpdates) 561 lock (m_perClientPatchUpdates)
512 { 562 {
513 // Set the flags for all clients so the tainted patches will be sent out 563 // Set the flags for all clients so the tainted patches will be sent out
514 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 564 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
515 { 565 {
516 pups.SetAll(m_scene.Heightmap.GetTerrainData()); 566 pups.SetAll(m_scene.Heightmap.GetTerrainData());
517 } 567 }
@@ -521,13 +571,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
521 // ITerrainModule.PushTerrain() 571 // ITerrainModule.PushTerrain()
522 public void PushTerrain(IClientAPI pClient) 572 public void PushTerrain(IClientAPI pClient)
523 { 573 {
524 // If view distance based, set the modified patch bits and the frame event will send the updates
525 if (m_sendTerrainUpdatesByViewDistance) 574 if (m_sendTerrainUpdatesByViewDistance)
526 { 575 {
527 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 576 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
528 if (presence != null) 577 if (presence != null)
529 { 578 {
530 lock(m_perClientPatchUpdates) 579 lock (m_perClientPatchUpdates)
531 { 580 {
532 PatchUpdates pups; 581 PatchUpdates pups;
533 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) 582 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
@@ -536,7 +585,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
536 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence); 585 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
537 m_perClientPatchUpdates.Add(presence.UUID, pups); 586 m_perClientPatchUpdates.Add(presence.UUID, pups);
538 } 587 }
539 // By setting all to modified, the next update tick will send the patches
540 pups.SetAll(true); 588 pups.SetAll(true);
541 } 589 }
542 } 590 }
@@ -547,6 +595,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
547 pClient.SendLayerData(new float[10]); 595 pClient.SendLayerData(new float[10]);
548 } 596 }
549 } 597 }
598
550 #region Plugin Loading Methods 599 #region Plugin Loading Methods
551 600
552 private void LoadPlugins() 601 private void LoadPlugins()
@@ -595,7 +644,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
595 { 644 {
596 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); 645 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
597 m_loaders[terLoader.FileExtension] = terLoader; 646 m_loaders[terLoader.FileExtension] = terLoader;
598 m_log.Info("L ... " + typeName); 647 m_log.Debug("L ... " + typeName);
599 } 648 }
600 } 649 }
601 catch(AmbiguousMatchException) 650 catch(AmbiguousMatchException)
@@ -611,12 +660,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
611 if (!m_plugineffects.ContainsKey(pluginName)) 660 if (!m_plugineffects.ContainsKey(pluginName))
612 { 661 {
613 m_plugineffects.Add(pluginName, effect); 662 m_plugineffects.Add(pluginName, effect);
614 m_log.Info("E ... " + pluginName); 663 m_log.Debug("E ... " + pluginName);
615 } 664 }
616 else 665 else
617 { 666 {
618 m_plugineffects[pluginName] = effect; 667 m_plugineffects[pluginName] = effect;
619 m_log.Info("E ... " + pluginName + " (Replaced)"); 668 m_log.Debug("E ... " + pluginName + " (Replaced)");
620 } 669 }
621 } 670 }
622 } 671 }
@@ -636,7 +685,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
636 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere(); 685 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere();
637 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere(); 686 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere();
638 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere(); 687 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere();
639 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert); 688 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
640 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere(); 689 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere();
641 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere(); 690 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere();
642 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere(); 691 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere();
@@ -647,9 +696,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
647 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea(); 696 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea();
648 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea(); 697 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea();
649 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); 698 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
650 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); 699 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
651 700
652 // Terrain Modifier operations 701 // Terrain Modifier operations
702
653 m_modifyOperations["min"] = new MinModifier(this); 703 m_modifyOperations["min"] = new MinModifier(this);
654 m_modifyOperations["max"] = new MaxModifier(this); 704 m_modifyOperations["max"] = new MaxModifier(this);
655 m_modifyOperations["raise"] = new RaiseModifier(this); 705 m_modifyOperations["raise"] = new RaiseModifier(this);
@@ -673,22 +723,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
673 } 723 }
674 724
675 /// <summary> 725 /// <summary>
676 /// Saves the current state of the region into the revert map buffer. 726 /// Saves the current state of the region into the baked map buffer.
727
677 /// </summary> 728 /// </summary>
678 public void UpdateRevertMap() 729 public void UpdateBakedMap()
679 { 730 {
680 /* 731 m_baked = m_channel.MakeCopy();
681 int x; 732 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
682 for (x = 0; x < m_channel.Width; x++) 733 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
683 { 734 m_scene.Bakedmap = m_baked;
684 int y; 735 m_scene.SaveBakedTerrain();
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 } 736 }
693 737
694 /// <summary> 738 /// <summary>
@@ -715,11 +759,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
715 { 759 {
716 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 760 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
717 fileWidth, fileHeight, 761 fileWidth, fileHeight,
718 (int)m_scene.RegionInfo.RegionSizeX, 762 (int) m_scene.RegionInfo.RegionSizeX,
719 (int)m_scene.RegionInfo.RegionSizeY); 763 (int) m_scene.RegionInfo.RegionSizeY);
720 m_scene.Heightmap = channel; 764 m_scene.Heightmap = channel;
721 m_channel = channel; 765 m_channel = channel;
722 UpdateRevertMap(); 766 UpdateBakedMap();
723 } 767 }
724 768
725 return; 769 return;
@@ -781,39 +825,54 @@ namespace OpenSim.Region.CoreModules.World.Terrain
781 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave); 825 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave);
782 } 826 }
783 827
828
784 /// <summary> 829 /// <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 830 /// This is used to check to see of any of the terrain is tainted and, if so, schedule
787 /// updates for all the presences. 831 /// updates for all the presences.
788 /// This also checks to see if there are updates that need to be sent for each presence. 832 /// 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. 833 /// This is where the logic is to send terrain updates to clients.
790 /// </summary> 834 /// </summary>
791 private void EventManager_OnFrame() 835 /// doing it async, since currently this is 2 heavy for heartbeat
836 private void EventManager_TerrainCheckUpdates()
792 { 837 {
793 TerrainData terrData = m_channel.GetTerrainData(); 838 Util.FireAndForget(
839 EventManager_TerrainCheckUpdatesAsync);
840 }
841
842 object TerrainCheckUpdatesLock = new object();
794 843
795 bool shouldTaint = false; 844 private void EventManager_TerrainCheckUpdatesAsync(object o)
796 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 845 {
846 // dont overlap execution
847 if(Monitor.TryEnter(TerrainCheckUpdatesLock))
797 { 848 {
798 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 849 // this needs fixing
850 TerrainData terrData = m_channel.GetTerrainData();
851
852 bool shouldTaint = false;
853 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
799 { 854 {
800 if (terrData.IsTaintedAt(x, y)) 855 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
801 { 856 {
802 // Found a patch that was modified. Push this flag into the clients. 857 if (terrData.IsTaintedAt(x, y,true))
803 SendToClients(terrData, x, y); 858 {
804 shouldTaint = true; 859 // Found a patch that was modified. Push this flag into the clients.
860 SendToClients(terrData, x, y);
861 shouldTaint = true;
862 }
805 } 863 }
806 } 864 }
807 }
808 865
809 // This event also causes changes to be sent to the clients 866 // This event also causes changes to be sent to the clients
810 CheckSendingPatchesToClients(); 867 CheckSendingPatchesToClients();
811 868
812 // If things changes, generate some events 869 // If things changes, generate some events
813 if (shouldTaint) 870 if (shouldTaint)
814 { 871 {
815 m_scene.EventManager.TriggerTerrainTainted(); 872 m_scene.EventManager.TriggerTerrainTainted();
816 m_tainted = true; 873 m_tainted = true;
874 }
875 Monitor.Exit(TerrainCheckUpdatesLock);
817 } 876 }
818 } 877 }
819 878
@@ -883,8 +942,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
883 presence.ControllingClient.OnLandUndo -= client_OnLandUndo; 942 presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
884 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 943 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
885 } 944 }
886 945 lock (m_perClientPatchUpdates)
887 lock(m_perClientPatchUpdates)
888 m_perClientPatchUpdates.Remove(client); 946 m_perClientPatchUpdates.Remove(client);
889 } 947 }
890 948
@@ -898,12 +956,33 @@ namespace OpenSim.Region.CoreModules.World.Terrain
898 TerrainData terrData = m_channel.GetTerrainData(); 956 TerrainData terrData = m_channel.GetTerrainData();
899 957
900 bool wasLimited = false; 958 bool wasLimited = false;
901 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 959 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
902 { 960 {
903 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 961 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
904 { 962 {
905 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) 963 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
906 { 964 {
965 // If we should respect the estate settings then
966 // fixup and height deltas that don't respect them.
967 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
968 wasLimited |= LimitChannelChanges(terrData, x, y);
969 }
970 }
971 }
972 return wasLimited;
973 }
974
975 private bool EnforceEstateLimits(int startX, int startY, int endX, int endY)
976 {
977 TerrainData terrData = m_channel.GetTerrainData();
978
979 bool wasLimited = false;
980 for (int x = startX; x <= endX; x += Constants.TerrainPatchSize)
981 {
982 for (int y = startX; y <= endY; y += Constants.TerrainPatchSize)
983 {
984 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
985 {
907 // If we should respect the estate settings then 986 // If we should respect the estate settings then
908 // fixup and height deltas that don't respect them. 987 // fixup and height deltas that don't respect them.
909 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. 988 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
@@ -926,13 +1005,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
926 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; 1005 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
927 1006
928 // loop through the height map for this patch and compare it against 1007 // loop through the height map for this patch and compare it against
929 // the revert map 1008 // the baked map
930 for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) 1009 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
931 { 1010 {
932 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 1011 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
933 { 1012 {
934 float requestedHeight = terrData[x, y]; 1013 float requestedHeight = terrData[x, y];
935 float bakedHeight = (float)m_revert[x, y]; 1014 float bakedHeight = (float)m_baked[x, y];
936 float requestedDelta = requestedHeight - bakedHeight; 1015 float requestedDelta = requestedHeight - bakedHeight;
937 1016
938 if (requestedDelta > maxDelta) 1017 if (requestedDelta > maxDelta)
@@ -953,15 +1032,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
953 1032
954 private void client_OnLandUndo(IClientAPI client) 1033 private void client_OnLandUndo(IClientAPI client)
955 { 1034 {
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 } 1035 }
966 1036
967 /// <summary> 1037 /// <summary>
@@ -975,19 +1045,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
975 if (m_sendTerrainUpdatesByViewDistance) 1045 if (m_sendTerrainUpdatesByViewDistance)
976 { 1046 {
977 // Add that this patch needs to be sent to the accounting for each client. 1047 // Add that this patch needs to be sent to the accounting for each client.
978 lock(m_perClientPatchUpdates) 1048 lock (m_perClientPatchUpdates)
979 { 1049 {
980 m_scene.ForEachScenePresence(presence => 1050 m_scene.ForEachScenePresence(presence =>
981 {
982 PatchUpdates thisClientUpdates;
983 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
984 { 1051 {
985 // There is a ScenePresence without a send patch map. Create one. 1052 PatchUpdates thisClientUpdates;
986 thisClientUpdates = new PatchUpdates(terrData, presence); 1053 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
987 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates); 1054 {
1055 // There is a ScenePresence without a send patch map. Create one.
1056 thisClientUpdates = new PatchUpdates(terrData, presence);
1057 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
1058 }
1059 thisClientUpdates.SetByXY(x, y, true);
988 } 1060 }
989 thisClientUpdates.SetByXY(x, y, true);
990 }
991 ); 1061 );
992 } 1062 }
993 } 1063 }
@@ -998,7 +1068,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
998 //float[] heightMap = terrData.GetFloatsSerialized(); 1068 //float[] heightMap = terrData.GetFloatsSerialized();
999 float[] heightMap = new float[10]; 1069 float[] heightMap = new float[10];
1000 m_scene.ForEachClient( 1070 m_scene.ForEachClient(
1001 delegate(IClientAPI controller) 1071 delegate (IClientAPI controller)
1002 { 1072 {
1003 controller.SendLayerData(x / Constants.TerrainPatchSize, 1073 controller.SendLayerData(x / Constants.TerrainPatchSize,
1004 y / Constants.TerrainPatchSize, 1074 y / Constants.TerrainPatchSize,
@@ -1013,14 +1083,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1013 public int PatchX; 1083 public int PatchX;
1014 public int PatchY; 1084 public int PatchY;
1015 public float Dist; 1085 public float Dist;
1016
1017 public PatchesToSend(int pX, int pY, float pDist) 1086 public PatchesToSend(int pX, int pY, float pDist)
1018 { 1087 {
1019 PatchX = pX; 1088 PatchX = pX;
1020 PatchY = pY; 1089 PatchY = pY;
1021 Dist = pDist; 1090 Dist = pDist;
1022 } 1091 }
1023
1024 public int CompareTo(PatchesToSend other) 1092 public int CompareTo(PatchesToSend other)
1025 { 1093 {
1026 return Dist.CompareTo(other.Dist); 1094 return Dist.CompareTo(other.Dist);
@@ -1029,113 +1097,216 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1029 1097
1030 // Called each frame time to see if there are any patches to send to any of the 1098 // Called each frame time to see if there are any patches to send to any of the
1031 // ScenePresences. 1099 // 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. 1100 // Loop through all the per-client info and send any patches necessary.
1035 private void CheckSendingPatchesToClients() 1101 private void CheckSendingPatchesToClients()
1036 { 1102 {
1037 lock(m_perClientPatchUpdates) 1103 lock (m_perClientPatchUpdates)
1038 { 1104 {
1039 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 1105 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
1040 { 1106 {
1107 if(pups.Presence.IsDeleted)
1108 continue;
1109
1110 // limit rate acording to udp land queue state
1111 if (!pups.Presence.ControllingClient.CanSendLayerData())
1112 continue;
1113
1041 if (pups.HasUpdates()) 1114 if (pups.HasUpdates())
1042 { 1115 {
1043 // There is something that could be sent to this client. 1116 if (m_sendTerrainUpdatesByViewDistance)
1044 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1045 if (toSend.Count > 0)
1046 { 1117 {
1047 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}", 1118 // There is something that could be sent to this client.
1048 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName); 1119 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1049 // Sort the patches to send by the distance from the presence 1120 if (toSend.Count > 0)
1050 toSend.Sort();
1051 /* old way that sent individual patches
1052 foreach (PatchesToSend pts in toSend)
1053 {
1054 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1055 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1056 }
1057 */
1058
1059 // new way that sends all patches to the protocol so they can be sent in one block
1060 int[] xPieces = new int[toSend.Count];
1061 int[] yPieces = new int[toSend.Count];
1062 float[] patchPieces = new float[toSend.Count * 2];
1063 int pieceIndex = 0;
1064 foreach(PatchesToSend pts in toSend)
1065 { 1121 {
1066 patchPieces[pieceIndex++] = pts.PatchX; 1122 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
1067 patchPieces[pieceIndex++] = pts.PatchY; 1123 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
1124 // Sort the patches to send by the distance from the presence
1125 toSend.Sort();
1126 /*
1127 foreach (PatchesToSend pts in toSend)
1128 {
1129 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1130 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1131 }
1132 */
1133
1134 float[] patchPieces = new float[toSend.Count * 2];
1135 int pieceIndex = 0;
1136 foreach (PatchesToSend pts in toSend)
1137 {
1138 patchPieces[pieceIndex++] = pts.PatchX;
1139 patchPieces[pieceIndex++] = pts.PatchY;
1140 }
1141 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
1068 } 1142 }
1069 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces); 1143 if (pups.sendAll && toSend.Count < 1024)
1144 SendAllModifiedPatchs(pups);
1145 }
1146 else
1147 SendAllModifiedPatchs(pups);
1148 }
1149 }
1150 }
1151 }
1152 private void SendAllModifiedPatchs(PatchUpdates pups)
1153 {
1154 if (!pups.sendAll) // sanity
1155 return;
1156
1157 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1158 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1159
1160 if (pups.sendAllcurrentX >= limitX && pups.sendAllcurrentY >= limitY)
1161 {
1162 pups.sendAll = false;
1163 pups.sendAllcurrentX = 0;
1164 pups.sendAllcurrentY = 0;
1165 return;
1166 }
1167
1168 int npatchs = 0;
1169 List<PatchesToSend> patchs = new List<PatchesToSend>();
1170 int x = pups.sendAllcurrentX;
1171 int y = pups.sendAllcurrentY;
1172 // send it in the order viewer draws it
1173 // even if not best for memory scan
1174 for (; y < limitY; y++)
1175 {
1176 for (; x < limitX; x++)
1177 {
1178 if (pups.GetByPatch(x, y))
1179 {
1180 pups.SetByPatch(x, y, false);
1181 patchs.Add(new PatchesToSend(x, y, 0));
1182 if (++npatchs >= 128)
1183 {
1184 x++;
1185 break;
1070 } 1186 }
1071 } 1187 }
1072 } 1188 }
1189 if (npatchs >= 128)
1190 break;
1191 x = 0;
1192 }
1193
1194 if (x >= limitX && y >= limitY)
1195 {
1196 pups.sendAll = false;
1197 pups.sendAllcurrentX = 0;
1198 pups.sendAllcurrentY = 0;
1199 }
1200 else
1201 {
1202 pups.sendAllcurrentX = x;
1203 pups.sendAllcurrentY = y;
1204 }
1205
1206 npatchs = patchs.Count;
1207 if (npatchs > 0)
1208 {
1209 int[] xPieces = new int[npatchs];
1210 int[] yPieces = new int[npatchs];
1211 float[] patchPieces = new float[npatchs * 2];
1212 int pieceIndex = 0;
1213 foreach (PatchesToSend pts in patchs)
1214 {
1215 patchPieces[pieceIndex++] = pts.PatchX;
1216 patchPieces[pieceIndex++] = pts.PatchY;
1217 }
1218 pups.Presence.ControllingClient.SendLayerData(-npatchs, 0, patchPieces);
1073 } 1219 }
1074 } 1220 }
1075 1221
1076 // Compute a list of modified patches that are within our view distance.
1077 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups) 1222 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
1078 { 1223 {
1079 List<PatchesToSend> ret = new List<PatchesToSend>(); 1224 List<PatchesToSend> ret = new List<PatchesToSend>();
1080 1225
1226 int npatchs = 0;
1227
1081 ScenePresence presence = pups.Presence; 1228 ScenePresence presence = pups.Presence;
1082 if (presence == null) 1229 if (presence == null)
1083 return ret; 1230 return ret;
1084 1231
1085 Vector3 presencePos = presence.AbsolutePosition; 1232 float minz = presence.AbsolutePosition.Z;
1086 1233 if (presence.CameraPosition.Z < minz)
1087 // Before this distance check, the whole region just showed up. Adding the distance 1234 minz = presence.CameraPosition.Z;
1088 // check causes different things to happen for the current and adjacent regions. 1235
1089 // So, to keep legacy views, if the region is legacy sized, don't do distance check. 1236 // this limit should be max terrainheight + max draw
1090 bool isLegacySizedRegion = pups.Terrain.SizeX == Constants.RegionSize && pups.Terrain.SizeY == Constants.RegionSize; 1237 if (minz > 1500f)
1091 bool shouldCheckViewDistance = m_sendTerrainUpdatesByViewDistance && !isLegacySizedRegion; 1238 return ret;
1092 1239
1093 int startX = 0; 1240 int DrawDistance = (int)presence.DrawDistance;
1094 int endX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize; 1241
1095 int startY = 0; 1242 DrawDistance = DrawDistance / Constants.TerrainPatchSize;
1096 int endY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize; 1243
1097 1244 int testposX;
1098 // The following only reduces the size of area scanned for updates. Only significant for very large varregions. 1245 int testposY;
1099 if (shouldCheckViewDistance) 1246
1100 { 1247 if (Math.Abs(presence.AbsolutePosition.X - presence.CameraPosition.X) > 30
1101 // Compute the area of patches within our draw distance 1248 || Math.Abs(presence.AbsolutePosition.Y - presence.CameraPosition.Y) > 30)
1102 startX = (((int)(presencePos.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1249 {
1103 startX = Math.Max(startX, 0); 1250 testposX = (int)presence.CameraPosition.X / Constants.TerrainPatchSize;
1104 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1251 testposY = (int)presence.CameraPosition.Y / Constants.TerrainPatchSize;
1105 startY = (((int)(presencePos.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1252 }
1106 startY = Math.Max(startY, 0); 1253 else
1107 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1254 {
1108 endX = (((int)(presencePos.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1255 testposX = (int)presence.AbsolutePosition.X / Constants.TerrainPatchSize;
1109 endX = Math.Max(endX, 0); 1256 testposY = (int)presence.AbsolutePosition.Y / Constants.TerrainPatchSize;
1110 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1257 }
1111 endY = (((int)(presencePos.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1258 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1112 endY = Math.Max(endY, 0); 1259 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1113 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1260
1114 } 1261 // Compute the area of patches within our draw distance
1115 1262 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}>", 1263 if (startX < 0)
1117 // LogHeader, m_scene.RegionInfo.RegionName, 1264 startX = 0;
1118 // presence.DrawDistance, presencePos, presence.CameraPosition, 1265 else if (startX >= limitX)
1119 // isLegacySizeChildRegion, 1266 startX = limitX - 1;
1120 // startX, startY, endX, endY); 1267
1121 for(int x = startX; x < endX; x++) 1268 int startY = testposY - DrawDistance;
1122 { 1269 if (startY < 0)
1123 for(int y = startY; y < endY; y++) 1270 startY = 0;
1271 else if (startY >= limitY)
1272 startY = limitY - 1;
1273
1274 int endX = testposX + DrawDistance;
1275 if (endX < 0)
1276 endX = 0;
1277 else if (endX > limitX)
1278 endX = limitX;
1279
1280 int endY = testposY + DrawDistance;
1281 if (endY < 0)
1282 endY = 0;
1283 else if (endY > limitY)
1284 endY = limitY;
1285
1286 int distx;
1287 int disty;
1288 int distsq;
1289
1290 DrawDistance *= DrawDistance;
1291
1292 for (int x = startX; x < endX; x++)
1293 {
1294 for (int y = startY; y < endY; y++)
1124 { 1295 {
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)) 1296 if (pups.GetByPatch(x, y))
1128 { 1297 {
1129 //Check which has less distance, camera or avatar position, both have to be done. 1298 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 1299 disty = y - testposY;
1131 if (!shouldCheckViewDistance 1300 distsq = distx * distx + disty * disty;
1132 || Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50) 1301 if (distsq < DrawDistance)
1133 || Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
1134 { 1302 {
1135 //They can see it, send it to them
1136 pups.SetByPatch(x, y, false); 1303 pups.SetByPatch(x, y, false);
1137 float dist = Vector3.DistanceSquared(presencePos, patchPos); 1304 ret.Add(new PatchesToSend(x, y, (float)distsq));
1138 ret.Add(new PatchesToSend(x, y, dist)); 1305 if (npatchs++ > 1024)
1306 {
1307 y = endY;
1308 x = endX;
1309 }
1139 } 1310 }
1140 } 1311 }
1141 } 1312 }
@@ -1161,33 +1332,44 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1161 int zx = (int)(west + 0.5); 1332 int zx = (int)(west + 0.5);
1162 int zy = (int)(north + 0.5); 1333 int zy = (int)(north + 0.5);
1163 1334
1164 int dx; 1335 int startX = zx - n;
1165 for(dx=-n; dx<=n; dx++) 1336 if (startX < 0)
1337 startX = 0;
1338
1339 int startY = zy - n;
1340 if (startY < 0)
1341 startY = 0;
1342
1343 int endX = zx + n;
1344 if (endX >= m_channel.Width)
1345 endX = m_channel.Width - 1;
1346 int endY = zy + n;
1347 if (endY >= m_channel.Height)
1348 endY = m_channel.Height - 1;
1349
1350 int x, y;
1351
1352 for (x = startX; x <= endX; x++)
1166 { 1353 {
1167 int dy; 1354 for (y = startY; y <= endY; y++)
1168 for(dy=-n; dy<=n; dy++)
1169 { 1355 {
1170 int x = zx + dx; 1356 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 { 1357 {
1174 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) 1358 allowMask[x, y] = true;
1175 { 1359 allowed = true;
1176 allowMask[x, y] = true;
1177 allowed = true;
1178 }
1179 } 1360 }
1180 } 1361 }
1181 } 1362 }
1182 if (allowed) 1363 if (allowed)
1183 { 1364 {
1184 StoreUndoState(); 1365 StoreUndoState();
1185 m_painteffects[(StandardTerrainEffects)action].PaintEffect( 1366 m_painteffects[(StandardTerrainEffects) action].PaintEffect(
1186 m_channel, allowMask, west, south, height, size, seconds); 1367 m_channel, allowMask, west, south, height, size, seconds,
1368 startX, endX, startY, endY);
1187 1369
1188 //revert changes outside estate limits 1370 //block changes outside estate limits
1189 if (!god) 1371 if (!god)
1190 EnforceEstateLimits(); 1372 EnforceEstateLimits(startX, endX, startY, endY);
1191 } 1373 }
1192 } 1374 }
1193 else 1375 else
@@ -1202,22 +1384,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1202 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; 1384 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
1203 fillArea.Initialize(); 1385 fillArea.Initialize();
1204 1386
1205 int x; 1387 int startX = (int)west;
1206 for(x = 0; x < m_channel.Width; x++) 1388 int startY = (int)south;
1389 int endX = (int)east;
1390 int endY = (int)north;
1391
1392 if (startX < 0)
1393 startX = 0;
1394 else if (startX >= m_channel.Width)
1395 startX = m_channel.Width - 1;
1396
1397 if (endX < 0)
1398 endX = 0;
1399 else if (endX >= m_channel.Width)
1400 endX = m_channel.Width - 1;
1401
1402 if (startY < 0)
1403 startY = 0;
1404 else if (startY >= m_channel.Height)
1405 startY = m_channel.Height - 1;
1406
1407 if (endY < 0)
1408 endY = 0;
1409 else if (endY >= m_channel.Height)
1410 endY = m_channel.Height - 1;
1411
1412
1413 int x, y;
1414
1415 for (x = startX; x <= endX; x++)
1207 { 1416 {
1208 int y; 1417 for (y = startY; y <= endY; y++)
1209 for(y = 0; y < m_channel.Height; y++)
1210 { 1418 {
1211 if (x < east && x > west) 1419 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1212 { 1420 {
1213 if (y < north && y > south) 1421 fillArea[x, y] = true;
1214 { 1422 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 } 1423 }
1222 } 1424 }
1223 } 1425 }
@@ -1225,11 +1427,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1225 if (allowed) 1427 if (allowed)
1226 { 1428 {
1227 StoreUndoState(); 1429 StoreUndoState();
1228 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size); 1430 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size,
1431 startX, endX, startY, endY);
1229 1432
1230 //revert changes outside estate limits 1433 //block changes outside estate limits
1231 if (!god) 1434 if (!god)
1232 EnforceEstateLimits(); 1435 EnforceEstateLimits(startX, endX, startY, endY);
1233 } 1436 }
1234 } 1437 }
1235 else 1438 else
@@ -1260,37 +1463,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1260 1463
1261 private void StoreUndoState() 1464 private void StoreUndoState()
1262 { 1465 {
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 } 1466 }
1279 1467
1280 #region Console Commands 1468 #region Console Commands
1281 1469
1282 private void InterfaceLoadFile(Object[] args) 1470 private void InterfaceLoadFile(Object[] args)
1283 { 1471 {
1284 LoadFromFile((string)args[0]); 1472 LoadFromFile((string) args[0]);
1285 } 1473 }
1286 1474
1287 private void InterfaceLoadTileFile(Object[] args) 1475 private void InterfaceLoadTileFile(Object[] args)
1288 { 1476 {
1289 LoadFromFile((string)args[0], 1477 LoadFromFile((string) args[0],
1290 (int)args[1], 1478 (int) args[1],
1291 (int)args[2], 1479 (int) args[2],
1292 (int)args[3], 1480 (int) args[3],
1293 (int)args[4]); 1481 (int) args[4]);
1294 } 1482 }
1295 1483
1296 private void InterfaceSaveFile(Object[] args) 1484 private void InterfaceSaveFile(Object[] args)
@@ -1309,15 +1497,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1309 1497
1310 private void InterfaceBakeTerrain(Object[] args) 1498 private void InterfaceBakeTerrain(Object[] args)
1311 { 1499 {
1312 UpdateRevertMap(); 1500 UpdateBakedMap();
1313 } 1501 }
1314 1502
1315 private void InterfaceRevertTerrain(Object[] args) 1503 private void InterfaceRevertTerrain(Object[] args)
1316 { 1504 {
1317 int x, y; 1505 int x, y;
1318 for(x = 0; x < m_channel.Width; x++) 1506 for (x = 0; x < m_channel.Width; x++)
1319 for(y = 0; y < m_channel.Height; y++) 1507 for (y = 0; y < m_channel.Height; y++)
1320 m_channel[x, y] = m_revert[x, y]; 1508 m_channel[x, y] = m_baked[x, y];
1321 1509
1322 } 1510 }
1323 1511
@@ -1327,9 +1515,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1327 1515
1328 if (direction.ToLower().StartsWith("y")) 1516 if (direction.ToLower().StartsWith("y"))
1329 { 1517 {
1330 for(int x = 0; x < m_channel.Width; x++) 1518 for (int x = 0; x < m_channel.Width; x++)
1331 { 1519 {
1332 for(int y = 0; y < m_channel.Height / 2; y++) 1520 for (int y = 0; y < m_channel.Height / 2; y++)
1333 { 1521 {
1334 double height = m_channel[x, y]; 1522 double height = m_channel[x, y];
1335 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; 1523 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
@@ -1341,9 +1529,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1341 } 1529 }
1342 else if (direction.ToLower().StartsWith("x")) 1530 else if (direction.ToLower().StartsWith("x"))
1343 { 1531 {
1344 for(int y = 0; y < m_channel.Height; y++) 1532 for (int y = 0; y < m_channel.Height; y++)
1345 { 1533 {
1346 for(int x = 0; x < m_channel.Width / 2; x++) 1534 for (int x = 0; x < m_channel.Width / 2; x++)
1347 { 1535 {
1348 double height = m_channel[x, y]; 1536 double height = m_channel[x, y];
1349 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; 1537 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
@@ -1415,50 +1603,57 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1415 } 1603 }
1416 1604
1417 } 1605 }
1418
1419 } 1606 }
1420 1607
1421 private void InterfaceElevateTerrain(Object[] args) 1608 private void InterfaceElevateTerrain(Object[] args)
1422 { 1609 {
1610 double val = (double)args[0];
1611
1423 int x, y; 1612 int x, y;
1424 for(x = 0; x < m_channel.Width; x++) 1613 for (x = 0; x < m_channel.Width; x++)
1425 for(y = 0; y < m_channel.Height; y++) 1614 for (y = 0; y < m_channel.Height; y++)
1426 m_channel[x, y] += (double)args[0]; 1615 m_channel[x, y] += val;
1427 } 1616 }
1428 1617
1429 private void InterfaceMultiplyTerrain(Object[] args) 1618 private void InterfaceMultiplyTerrain(Object[] args)
1430 { 1619 {
1431 int x, y; 1620 int x, y;
1432 for(x = 0; x < m_channel.Width; x++) 1621 double val = (double)args[0];
1433 for(y = 0; y < m_channel.Height; y++) 1622
1434 m_channel[x, y] *= (double)args[0]; 1623 for (x = 0; x < m_channel.Width; x++)
1624 for (y = 0; y < m_channel.Height; y++)
1625 m_channel[x, y] *= val;
1435 } 1626 }
1436 1627
1437 private void InterfaceLowerTerrain(Object[] args) 1628 private void InterfaceLowerTerrain(Object[] args)
1438 { 1629 {
1439 int x, y; 1630 int x, y;
1440 for(x = 0; x < m_channel.Width; x++) 1631 double val = (double)args[0];
1441 for(y = 0; y < m_channel.Height; y++) 1632
1442 m_channel[x, y] -= (double)args[0]; 1633 for (x = 0; x < m_channel.Width; x++)
1634 for (y = 0; y < m_channel.Height; y++)
1635 m_channel[x, y] -= val;
1443 } 1636 }
1444 1637
1445 public void InterfaceFillTerrain(Object[] args) 1638 public void InterfaceFillTerrain(Object[] args)
1446 { 1639 {
1447 int x, y; 1640 int x, y;
1641 double val = (double)args[0];
1448 1642
1449 for(x = 0; x < m_channel.Width; x++) 1643 for (x = 0; x < m_channel.Width; x++)
1450 for(y = 0; y < m_channel.Height; y++) 1644 for (y = 0; y < m_channel.Height; y++)
1451 m_channel[x, y] = (double)args[0]; 1645 m_channel[x, y] = val;
1452 } 1646 }
1453 1647
1454 private void InterfaceMinTerrain(Object[] args) 1648 private void InterfaceMinTerrain(Object[] args)
1455 { 1649 {
1456 int x, y; 1650 int x, y;
1457 for(x = 0; x < m_channel.Width; x++) 1651 double val = (double)args[0];
1652 for (x = 0; x < m_channel.Width; x++)
1458 { 1653 {
1459 for(y = 0; y < m_channel.Height; y++) 1654 for(y = 0; y < m_channel.Height; y++)
1460 { 1655 {
1461 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1656 m_channel[x, y] = Math.Max(val, m_channel[x, y]);
1462 } 1657 }
1463 } 1658 }
1464 } 1659 }
@@ -1466,11 +1661,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1466 private void InterfaceMaxTerrain(Object[] args) 1661 private void InterfaceMaxTerrain(Object[] args)
1467 { 1662 {
1468 int x, y; 1663 int x, y;
1469 for(x = 0; x < m_channel.Width; x++) 1664 double val = (double)args[0];
1665 for (x = 0; x < m_channel.Width; x++)
1470 { 1666 {
1471 for(y = 0; y < m_channel.Height; y++) 1667 for(y = 0; y < m_channel.Height; y++)
1472 { 1668 {
1473 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1669 m_channel[x, y] = Math.Min(val, m_channel[x, y]);
1474 } 1670 }
1475 } 1671 }
1476 } 1672 }
@@ -1620,9 +1816,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1620 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); 1816 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");
1621 1817
1622 Command bakeRegionCommand = 1818 Command bakeRegionCommand =
1623 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); 1819 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions baked map.");
1624 Command revertRegionCommand = 1820 Command revertRegionCommand =
1625 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); 1821 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the baked map terrain into the regions heightmap.");
1626 1822
1627 Command flipCommand = 1823 Command flipCommand =
1628 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis"); 1824 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/TerrainModuleTests.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs
index 0563ad0..6a832bc 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs
@@ -45,8 +45,8 @@ namespace OpenSim.Region.CoreModules.Terrain.Tests
45 //UUID userId = TestHelpers.ParseTail(0x1); 45 //UUID userId = TestHelpers.ParseTail(0x1);
46 46
47 TerrainModule tm = new TerrainModule(); 47 TerrainModule tm = new TerrainModule();
48 Scene scene = new SceneHelpers().SetupScene(); 48 Scene scene = new SceneHelpers().SetupScene();
49 SceneHelpers.SetupSceneModules(scene, tm); 49 SceneHelpers.SetupSceneModules(scene, tm);
50 50
51 // Fillheight of 30 51 // Fillheight of 30
52 { 52 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index 29e80ef..8e77962 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -60,12 +60,13 @@ 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).");
67 Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128)."); 68 Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128).");
68 Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128)."); 69// Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128).");
69 // 70 //
70 // Test LowerSphere 71 // Test LowerSphere
71 // 72 //
@@ -79,13 +80,14 @@ 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).");
86 Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128)."); 88 Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128).");
87 Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128)."); 89 Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128).");
88 Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128)."); 90// Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128).");
89 } 91 }
90 92
91 [Test] 93 [Test]
diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
index 3f5d375..4cee7a5 100644
--- a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
+++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
@@ -39,14 +39,14 @@ namespace OpenSim.Region.CoreModules.World.Vegetation
39{ 39{
40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VegetationModule")] 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VegetationModule")]
41 public class VegetationModule : INonSharedRegionModule, IVegetationModule 41 public class VegetationModule : INonSharedRegionModule, IVegetationModule
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 protected Scene m_scene; 45 protected Scene m_scene;
46 46
47 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree }; 47 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree };
48 public PCode[] CreationCapabilities { get { return creationCapabilities; } } 48 public PCode[] CreationCapabilities { get { return creationCapabilities; } }
49 49
50 public void Initialise(IConfigSource source) 50 public void Initialise(IConfigSource source)
51 { 51 {
52 } 52 }
@@ -83,10 +83,10 @@ namespace OpenSim.Region.CoreModules.World.Vegetation
83 treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree; 83 treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree;
84 treeShape.Scale = scale; 84 treeShape.Scale = scale;
85 treeShape.State = (byte)treeType; 85 treeShape.State = (byte)treeType;
86 86
87 return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); 87 return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape);
88 } 88 }
89 89
90 public SceneObjectGroup CreateEntity( 90 public SceneObjectGroup CreateEntity(
91 UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 91 UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
92 { 92 {
@@ -95,22 +95,23 @@ namespace OpenSim.Region.CoreModules.World.Vegetation
95 m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); 95 m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name);
96 return null; 96 return null;
97 } 97 }
98 98
99 SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); 99 SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
100 SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID); 100 SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID);
101 101
102 // if grass or tree, make phantom 102 // if grass or tree, make phantom
103 //rootPart.TrimPermissions(); 103 //rootPart.TrimPermissions();
104 rootPart.AddFlag(PrimFlags.Phantom); 104 rootPart.AddFlag(PrimFlags.Phantom);
105 if (rootPart.Shape.PCode != (byte)PCode.Grass) 105 if (rootPart.Shape.PCode != (byte)PCode.Grass)
106 AdaptTree(ref shape); 106 AdaptTree(ref shape);
107 107
108 m_scene.AddNewSceneObject(sceneObject, true);
109 sceneObject.SetGroup(groupID, null); 108 sceneObject.SetGroup(groupID, null);
110 109 m_scene.AddNewSceneObject(sceneObject, true);
110 sceneObject.InvalidateDeepEffectivePerms();
111
111 return sceneObject; 112 return sceneObject;
112 } 113 }
113 114
114 protected void AdaptTree(ref PrimitiveBaseShape tree) 115 protected void AdaptTree(ref PrimitiveBaseShape tree)
115 { 116 {
116 // Tree size has to be adapted depending on its type 117 // Tree size has to be adapted depending on its type
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 9534ad3..226b330 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 {
@@ -225,7 +226,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
225 float pctX = (float)x / 255f; 226 float pctX = (float)x / 255f;
226 float pctY = (float)y / 255f; 227 float pctY = (float)y / 255f;
227 228
228 // Use bilinear interpolation between the four corners of start height and 229 // Use bilinear interpolation between the four corners of start height and
229 // height range to select the current values at this position 230 // height range to select the current values at this position
230 float startHeight = ImageUtils.Bilinear( 231 float startHeight = ImageUtils.Bilinear(
231 startHeights[0], 232 startHeights[0],
@@ -256,7 +257,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
256 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; 257 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
257 float noise = (lowFreq + highFreq) * 2f; 258 float noise = (lowFreq + highFreq) * 2f;
258 259
259 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it 260 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
260 float layer = ((height + noise - startHeight) / heightRange) * 4f; 261 float layer = ((height + noise - startHeight) / heightRange) * 4f;
261 if (Single.IsNaN(layer)) 262 if (Single.IsNaN(layer))
262 layer = 0f; 263 layer = 0f;
@@ -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 383a67f..d094bee 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -35,14 +35,14 @@ using System.Reflection;
35using CSJ2K; 35using CSJ2K;
36using Nini.Config; 36using Nini.Config;
37using log4net; 37using log4net;
38using Rednettle.Warp3D; 38using Warp3D;
39using Mono.Addins; 39using Mono.Addins;
40 40
41using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.PhysicsModules.SharedBase; 44//using OpenSim.Region.PhysicsModules.SharedBase;
45using OpenSim.Services.Interfaces; 45//using OpenSim.Services.Interfaces;
46 46
47using OpenMetaverse; 47using OpenMetaverse;
48using OpenMetaverse.Assets; 48using OpenMetaverse.Assets;
@@ -51,6 +51,7 @@ using OpenMetaverse.Rendering;
51using OpenMetaverse.StructuredData; 51using OpenMetaverse.StructuredData;
52 52
53using WarpRenderer = global::Warp3D.Warp3D; 53using WarpRenderer = global::Warp3D.Warp3D;
54using System.Drawing.Drawing2D;
54 55
55namespace OpenSim.Region.CoreModules.World.Warp3DMap 56namespace OpenSim.Region.CoreModules.World.Warp3DMap
56{ 57{
@@ -76,10 +77,19 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
76 private bool m_texturePrims = true; // true if should texture the rendered prims 77 private bool m_texturePrims = true; // true if should texture the rendered prims
77 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it 78 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it
78 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes 79 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes
79 private bool m_useAntiAliasing = false; // true if to anti-alias the rendered image 80 private String m_cacheDirectory = "";
80
81 private bool m_Enabled = false; 81 private bool m_Enabled = false;
82 82
83// private bool m_enable_date = false;
84// private bool m_enable_regionName = false;
85 private bool m_enable_regionPosition = false;
86 private bool m_enable_refreshEveryMonth = false;
87// private bool m_enable_HostedBy = false;
88// private String m_enable_HostedByText = "";
89
90 // private Bitmap lastImage = null;
91 private DateTime lastImageTime = DateTime.MinValue;
92
83 #region Region Module interface 93 #region Region Module interface
84 94
85 public void Initialise(IConfigSource source) 95 public void Initialise(IConfigSource source)
@@ -94,9 +104,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
94 104
95 m_Enabled = true; 105 m_Enabled = true;
96 106
97 m_drawPrimVolume 107 m_drawPrimVolume
98 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume); 108 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
99 m_textureTerrain 109 m_textureTerrain
100 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain); 110 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
101 m_texturePrims 111 m_texturePrims
102 = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims); 112 = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
@@ -104,9 +114,19 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
104 = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize); 114 = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
105 m_renderMeshes 115 m_renderMeshes
106 = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes); 116 = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
107 m_useAntiAliasing 117 m_cacheDirectory
108 = Util.GetConfigVarFromSections<bool>(m_config, "UseAntiAliasing", configSections, m_useAntiAliasing); 118 = Util.GetConfigVarFromSections<string>(m_config, "CacheDirectory", configSections, System.IO.Path.Combine(Util.cacheDir(), "MapImageCache"));
109 119
120
121// m_enable_date = Util.GetConfigVarFromSections<bool>(m_config, "enableDate", configSections, false);
122// m_enable_regionName = Util.GetConfigVarFromSections<bool>(m_config, "enableName", configSections, false);
123 m_enable_regionPosition = Util.GetConfigVarFromSections<bool>(m_config, "enablePosition", configSections, false);
124 m_enable_refreshEveryMonth = Util.GetConfigVarFromSections<bool>(m_config, "RefreshEveryMonth", configSections, true);
125// m_enable_HostedBy = Util.GetConfigVarFromSections<bool>(m_config, "enableHostedBy", configSections, false);
126// m_enable_HostedByText = Util.GetConfigVarFromSections<String>(m_config, "HosterText", configSections, String.Empty);
127
128 if (!Directory.Exists(m_cacheDirectory))
129 Directory.CreateDirectory(m_cacheDirectory);
110 } 130 }
111 131
112 public void AddRegion(Scene scene) 132 public void AddRegion(Scene scene)
@@ -118,14 +138,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
118 138
119 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 139 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
120 if (renderers.Count > 0) 140 if (renderers.Count > 0)
121 { 141 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 142 else
126 { 143 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 144
130 m_scene.RegisterModuleInterface<IMapImageGenerator>(this); 145 m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
131 } 146 }
@@ -155,21 +170,149 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
155 #endregion 170 #endregion
156 171
157 #region IMapImageGenerator Members 172 #region IMapImageGenerator Members
173/*
174 public static string fillInt(int _i, int _l)
175 {
176 String _return = _i.ToString();
177
178 while(_return.Length < _l)
179 {
180 _return = 0 + _return;
181 }
182
183 return _return;
184 }
185
186 public static int getCurrentUnixTime()
187 {
188 return (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
189 }
190
191 public static String unixTimeToDateString(int unixTime)
192 {
193 DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
194 long unixTimeStampInTicks = (long)(unixTime * TimeSpan.TicksPerSecond);
195 DateTime _date = new DateTime(unixStart.Ticks + unixTimeStampInTicks, System.DateTimeKind.Utc);
158 196
197 return fillInt(_date.Day, 2) + "." + fillInt(_date.Month, 2) + "." + fillInt(_date.Year, 4) + " " + fillInt(_date.Hour, 2) + ":" + fillInt(_date.Minute, 2);
198 }
199
200 private void writeDateOnMap(ref Bitmap _map)
201 {
202 RectangleF rectf = new RectangleF(2, 1, 200, 25);
203
204 Graphics g = Graphics.FromImage(_map);
205 g.SmoothingMode = SmoothingMode.AntiAlias;
206 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
207 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
208 g.DrawString(unixTimeToDateString(getCurrentUnixTime()), new Font("Arial", 8), Brushes.White, rectf);
209 g.Flush();
210 }
211
212 private void writeNameOnMap(ref Bitmap _map)
213 {
214 RectangleF rectf = new RectangleF(2, m_scene.RegionInfo.RegionSizeX - 15, 200, 25);
215
216 Graphics g = Graphics.FromImage(_map);
217 g.SmoothingMode = SmoothingMode.AntiAlias;
218 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
219 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
220 g.DrawString(m_scene.Name, new Font("Arial", 8), Brushes.White, rectf);
221 g.Flush();
222 }
223*/
224 private void writePositionOnMap(ref Bitmap _map)
225 {
226 RectangleF rectf = new RectangleF(m_scene.RegionInfo.RegionSizeY - 75, m_scene.RegionInfo.RegionSizeX - 15, 80, 25);
227
228 Graphics g = Graphics.FromImage(_map);
229 g.SmoothingMode = SmoothingMode.AntiAlias;
230 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
231 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
232 g.DrawString("<" + m_scene.RegionInfo.RegionLocX + " " + m_scene.RegionInfo.RegionLocY + ">", new Font("Arial", 8), Brushes.White, rectf);
233 g.Flush();
234 }
235/*
236 private void writeHostedByOnMap(ref Bitmap _map)
237 {
238 RectangleF rectf = new RectangleF(2, m_scene.RegionInfo.RegionSizeX - 15, 200, 25);
239
240 Graphics g = Graphics.FromImage(_map);
241 g.SmoothingMode = SmoothingMode.AntiAlias;
242 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
243 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
244 g.DrawString(m_enable_HostedByText, new Font("Arial", 8), Brushes.Gray, rectf);
245 g.Flush();
246 }
247*/
248 public Bitmap CreateMapTileForce()
249 {
250 m_log.Info("[MAPTILE]: Forcing a map tile regenerate.");
251 File.Delete(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
252 return CreateMapTile();
253 }
159 public Bitmap CreateMapTile() 254 public Bitmap CreateMapTile()
160 { 255 {
161 // Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); 256 if ((File.GetCreationTime(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")).Month != DateTime.Now.Month) && (m_enable_refreshEveryMonth == true))
162 // Camera above the middle of the region 257 {
163 Vector3 camPos = new Vector3( 258 m_log.InfoFormat("[MAPTILE]: Clearing old map tile out of cache {0} {1}.",
164 m_scene.RegionInfo.RegionSizeX/2 - 0.5f, 259 File.GetCreationTime(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")).Month, DateTime.Now.Month);
165 m_scene.RegionInfo.RegionSizeY/2 - 0.5f, 260 File.Delete(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
166 221.7025033688163f); 261 }
167 // Viewport viewing down onto the region 262
168 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, 263 if(File.Exists(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp")))
169 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, 264 {
170 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY ); 265 return new Bitmap(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
171 // Fill the viewport and return the image 266 }
172 return CreateMapTile(viewport, false); 267 else
268 {
269 m_log.Info("[MAPTILE]: Actually generating a map tile.");
270 /* this must be on all map, not just its image
271 if ((DateTime.Now - lastImageTime).TotalSeconds < 3600)
272 {
273 return (Bitmap)lastImage.Clone();
274 }
275 */
276
277 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
278 if (renderers.Count > 0)
279 {
280 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
281 }
282
283 Vector3 camPos = new Vector3(
284 m_scene.RegionInfo.RegionSizeX / 2 - 0.5f,
285 m_scene.RegionInfo.RegionSizeY / 2 - 0.5f,
286 221.7025033688163f);
287 // Viewport viewing down onto the region
288 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
289 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
290 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY);
291
292 Bitmap tile = CreateMapTile(viewport, false);
293
294// if (m_enable_date)
295// writeDateOnMap(ref tile);
296
297// if (m_enable_regionName)
298// writeNameOnMap(ref tile);
299
300 if (m_enable_regionPosition)
301 writePositionOnMap(ref tile);
302
303// if (m_enable_HostedBy)
304// writeHostedByOnMap(ref tile);
305
306 tile.Save(System.IO.Path.Combine(m_cacheDirectory, m_scene.RegionInfo.RegionID + ".bmp"));
307 m_primMesher = null;
308 return tile;
309
310 /*
311 lastImage = tile;
312 lastImageTime = DateTime.Now;
313 return (Bitmap)lastImage.Clone();
314 */
315 }
173 } 316 }
174 317
175 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 318 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
@@ -185,21 +328,14 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
185 int width = viewport.Width; 328 int width = viewport.Width;
186 int height = viewport.Height; 329 int height = viewport.Height;
187 330
188 if (m_useAntiAliasing)
189 {
190 width *= 2;
191 height *= 2;
192 }
193
194 WarpRenderer renderer = new WarpRenderer(); 331 WarpRenderer renderer = new WarpRenderer();
195 332
196 renderer.CreateScene(width, height); 333 if(!renderer.CreateScene(width, height))
197 renderer.Scene.autoCalcNormals = false; 334 return new Bitmap(width,height);
198 335
199 #region Camera 336 #region Camera
200 337
201 warp_Vector pos = ConvertVector(viewport.Position); 338 warp_Vector pos = ConvertVector(viewport.Position);
202 pos.z -= 0.001f; // Works around an issue with the Warp3D camera
203 warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection)); 339 warp_Vector lookat = warp_Vector.add(ConvertVector(viewport.Position), ConvertVector(viewport.LookDirection));
204 340
205 renderer.Scene.defaultCamera.setPos(pos); 341 renderer.Scene.defaultCamera.setPos(pos);
@@ -207,9 +343,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
207 343
208 if (viewport.Orthographic) 344 if (viewport.Orthographic)
209 { 345 {
210 renderer.Scene.defaultCamera.isOrthographic = true; 346 renderer.Scene.defaultCamera.setOrthographic(true,viewport.OrthoWindowWidth, viewport.OrthoWindowHeight);
211 renderer.Scene.defaultCamera.orthoViewWidth = viewport.OrthoWindowWidth;
212 renderer.Scene.defaultCamera.orthoViewHeight = viewport.OrthoWindowHeight;
213 } 347 }
214 else 348 else
215 { 349 {
@@ -231,24 +365,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
231 renderer.Render(); 365 renderer.Render();
232 Bitmap bitmap = renderer.Scene.getImage(); 366 Bitmap bitmap = renderer.Scene.getImage();
233 367
234 if (m_useAntiAliasing) 368 renderer.Scene.destroy();
235 { 369 renderer.Reset();
236 using (Bitmap origBitmap = bitmap)
237 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
238 }
239
240 // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
241 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
242 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
243 // this map tile simply takes a lot of memory.
244 foreach (var o in renderer.Scene.objectData.Values)
245 {
246 warp_Object obj = (warp_Object)o;
247 obj.vertexData = null;
248 obj.triangleData = null;
249 }
250
251 renderer.Scene.removeAllObjects();
252 renderer = null; 370 renderer = null;
253 viewport = null; 371 viewport = null;
254 372
@@ -284,16 +402,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
284 { 402 {
285 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 403 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
286 404
287 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
288 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
289 waterHeight,
290 m_scene.RegionInfo.RegionSizeY/2 - 0.5f );
291
292 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR)); 405 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR));
293 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif 406 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif
294 waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); 407 waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f));
295 renderer.Scene.addMaterial("WaterColor", waterColorMaterial); 408 renderer.Scene.addMaterial("WaterColor", waterColorMaterial);
296 renderer.SetObjectMaterial("Water", "WaterColor"); 409
410 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / 256; x++)
411 {
412 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / 256; y++)
413 {
414 renderer.AddPlane("Water-" + x + "-" + y, 256);
415 renderer.Scene.sceneobject("Water-" + x + "-" + y).setPos(256 * x, waterHeight, 256 * y);
416 renderer.SetObjectMaterial("Water-" + x + "-" + y, "WaterColor");
417 }
418 }
297 } 419 }
298 420
299 // Add a terrain to the renderer. 421 // Add a terrain to the renderer.
@@ -303,53 +425,53 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
303 { 425 {
304 ITerrainChannel terrain = m_scene.Heightmap; 426 ITerrainChannel terrain = m_scene.Heightmap;
305 427
428 float regionsx = m_scene.RegionInfo.RegionSizeX;
429 float regionsy = m_scene.RegionInfo.RegionSizeY;
430
306 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding 431 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
307 float diff = (float)m_scene.RegionInfo.RegionSizeX / 256f; 432 float diff = regionsx / 256f;
433
434 int npointsx =(int)(regionsx / diff);
435 int npointsy =(int)(regionsy / diff);
308 436
309 warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2); 437 float invsx = 1.0f / regionsx;
438 float invsy = 1.0f / (float)m_scene.RegionInfo.RegionSizeY;
310 439
311 // Create all the vertices for the terrain 440 // Create all the vertices for the terrain
312 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff) 441 warp_Object obj = new warp_Object();
442 for (float y = 0; y < regionsy; y += diff)
313 { 443 {
314 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff) 444 for (float x = 0; x < regionsx; x += diff)
315 { 445 {
316 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]); 446 warp_Vector pos = ConvertVector(x , y , (float)terrain[(int)x, (int)y]);
317 obj.addVertex(new warp_Vertex(pos, 447 obj.addVertex(new warp_Vertex(pos, x * invsx, 1.0f - y * invsy));
318 x / (float)m_scene.RegionInfo.RegionSizeX,
319 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY) );
320 } 448 }
321 } 449 }
322 450
323 // Now that we have all the vertices, make another pass and create 451 // Now that we have all the vertices, make another pass and
324 // the normals for each of the surface triangles and 452 // create the list of triangle indices.
325 // create the list of triangle indices. 453 float invdiff = 1.0f / diff;
326 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff) 454 int limx = npointsx - 1;
455 int limy = npointsy - 1;
456 for (float y = 0; y < regionsy; y += diff)
327 { 457 {
328 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff) 458 for (float x = 0; x < regionsx; x += diff)
329 { 459 {
330 float newX = x / diff; 460 float newX = x * invdiff;
331 float newY = y / diff; 461 float newY = y * invdiff;
332 if (newX < 255 && newY < 255) 462 if (newX < limx && newY < limy)
333 { 463 {
334 int v = (int)newY * 256 + (int)newX; 464 int v = (int)newY * npointsx + (int)newX;
335
336 // Normal for a triangle made up of three adjacent vertices
337 Vector3 v1 = new Vector3(newX, newY, (float)terrain[(int)x, (int)y]);
338 Vector3 v2 = new Vector3(newX + 1, newY, (float)terrain[(int)(x + 1), (int)y]);
339 Vector3 v3 = new Vector3(newX, newY + 1, (float)terrain[(int)x, ((int)(y + 1))]);
340 warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
341 norm = norm.reverse();
342 obj.vertex(v).n = norm;
343 465
344 // Make two triangles for each of the squares in the grid of vertices 466 // Make two triangles for each of the squares in the grid of vertices
345 obj.addTriangle( 467 obj.addTriangle(
346 v, 468 v,
347 v + 1, 469 v + 1,
348 v + 256); 470 v + npointsx);
349 471
350 obj.addTriangle( 472 obj.addTriangle(
351 v + 256 + 1, 473 v + npointsx + 1,
352 v + 256, 474 v + npointsx,
353 v + 1); 475 v + 1);
354 } 476 }
355 } 477 }
@@ -382,18 +504,15 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
382 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); 504 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
383 505
384 warp_Texture texture; 506 warp_Texture texture;
385 using ( 507 using (Bitmap image = TerrainSplat.Splat(
386 Bitmap image 508 terrain, textureIDs, startHeights, heightRanges,
387 = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges,
388 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) 509 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
389 {
390 texture = new warp_Texture(image); 510 texture = new warp_Texture(image);
391 }
392 511
393 warp_Material material = new warp_Material(texture); 512 warp_Material material = new warp_Material(texture);
394 material.setReflectivity(50); 513 material.setReflectivity(50);
395 renderer.Scene.addMaterial("TerrainColor", material); 514 renderer.Scene.addMaterial("TerrainColor", material);
396 renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif 515 renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif
397 renderer.SetObjectMaterial("Terrain", "TerrainColor"); 516 renderer.SetObjectMaterial("Terrain", "TerrainColor");
398 } 517 }
399 518
@@ -414,11 +533,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
414 private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, 533 private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim,
415 bool useTextures) 534 bool useTextures)
416 { 535 {
417 const float MIN_SIZE = 2f; 536 const float MIN_SIZE_SQUARE = 4f;
418 537
419 if ((PCode)prim.Shape.PCode != PCode.Prim) 538 if ((PCode)prim.Shape.PCode != PCode.Prim)
420 return; 539 return;
421 if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE) 540 float primScaleLenSquared = prim.Scale.LengthSquared();
541
542 if (primScaleLenSquared < MIN_SIZE_SQUARE)
422 return; 543 return;
423 544
424 FacetedMesh renderMesh = null; 545 FacetedMesh renderMesh = null;
@@ -454,11 +575,11 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
454 sculpt.Dispose(); 575 sculpt.Dispose();
455 } 576 }
456 } 577 }
457 catch (Exception e) 578 catch /*(Exception e)*/
458 { 579 {
459 Vector3 objectPos = prim.ParentGroup.RootPart.AbsolutePosition; 580 Vector3 objectPos = prim.ParentGroup.RootPart.AbsolutePosition;
460//// TODO - print out owner of SceneObjectPart prim. 581//// TODO - print out owner of SceneObjectPart prim.
461 m_log.Warn(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0} @ {1},{2},{3} - {4}.", 582 m_log.Error(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0} @ {1},{2},{3} - {4}.",
462 omvPrim.Sculpt.SculptTexture, objectPos.X, objectPos.Y, objectPos.Z, 583 omvPrim.Sculpt.SculptTexture, objectPos.X, objectPos.Y, objectPos.Z,
463 prim.ParentGroup.RootPart.Name)); 584 prim.ParentGroup.RootPart.Name));
464 } 585 }
@@ -477,20 +598,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
477 if (renderMesh == null) 598 if (renderMesh == null)
478 return; 599 return;
479 600
480 warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
481 warp_Quaternion primRot = ConvertQuaternion(prim.RotationOffset);
482
483 warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);
484
485 if (prim.ParentID != 0)
486 {
487 SceneObjectGroup group = m_scene.SceneGraph.GetGroupByPrim(prim.LocalId);
488 if (group != null)
489 m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootPart.RotationOffset)));
490 }
491
492 warp_Vector primScale = ConvertVector(prim.Scale);
493
494 string primID = prim.UUID.ToString(); 601 string primID = prim.UUID.ToString();
495 602
496 // Create the prim faces 603 // Create the prim faces
@@ -498,27 +605,18 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
498 for (int i = 0; i < renderMesh.Faces.Count; i++) 605 for (int i = 0; i < renderMesh.Faces.Count; i++)
499 { 606 {
500 Face face = renderMesh.Faces[i]; 607 Face face = renderMesh.Faces[i];
501 string meshName = primID + "-Face-" + i.ToString(); 608 string meshName = primID + i.ToString();
502 609
503 // Avoid adding duplicate meshes to the scene 610 // Avoid adding duplicate meshes to the scene
504 if (renderer.Scene.objectData.ContainsKey(meshName)) 611 if (renderer.Scene.objectData.ContainsKey(meshName))
505 {
506 continue; 612 continue;
507 }
508
509 warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count / 3);
510 613
614 warp_Object faceObj = new warp_Object();
511 for (int j = 0; j < face.Vertices.Count; j++) 615 for (int j = 0; j < face.Vertices.Count; j++)
512 { 616 {
513 Vertex v = face.Vertices[j]; 617 Vertex v = face.Vertices[j];
514
515 warp_Vector pos = ConvertVector(v.Position); 618 warp_Vector pos = ConvertVector(v.Position);
516 warp_Vector norm = ConvertVector(v.Normal); 619 warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y);
517
518 if (prim.Shape.SculptTexture == UUID.Zero)
519 norm = norm.reverse();
520 warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y);
521
522 faceObj.addVertex(vert); 620 faceObj.addVertex(vert);
523 } 621 }
524 622
@@ -533,17 +631,19 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
533 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); 631 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
534 Color4 faceColor = GetFaceColor(teFace); 632 Color4 faceColor = GetFaceColor(teFace);
535 string materialName = String.Empty; 633 string materialName = String.Empty;
536 if (m_texturePrims && prim.Scale.LengthSquared() > m_texturePrimSize*m_texturePrimSize) 634 if (m_texturePrims && primScaleLenSquared > m_texturePrimSize*m_texturePrimSize)
537 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); 635 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
538 else 636 else
539 materialName = GetOrCreateMaterial(renderer, faceColor); 637 materialName = GetOrCreateMaterial(renderer, faceColor);
540 638
639 warp_Vector primPos = ConvertVector(prim.GetWorldPosition());
640 warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation());
641 warp_Matrix m = warp_Matrix.quaternionMatrix(primRot);
541 faceObj.transform(m); 642 faceObj.transform(m);
542 faceObj.setPos(primPos); 643 faceObj.setPos(primPos);
543 faceObj.scaleSelf(primScale.x, primScale.y, primScale.z); 644 faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y);
544 645
545 renderer.Scene.addObject(meshName, faceObj); 646 renderer.Scene.addObject(meshName, faceObj);
546
547 renderer.SetObjectMaterial(meshName, materialName); 647 renderer.SetObjectMaterial(meshName, materialName);
548 } 648 }
549 } 649 }
@@ -576,7 +676,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
576 676
577 if (!fetched) 677 if (!fetched)
578 { 678 {
579 // Fetch the texture, decode and get the average color, 679 // Fetch the texture, decode and get the average color,
580 // then save it to a temporary metadata asset 680 // then save it to a temporary metadata asset
581 AssetBase textureAsset = m_scene.AssetService.Get(face.TextureID.ToString()); 681 AssetBase textureAsset = m_scene.AssetService.Get(face.TextureID.ToString());
582 if (textureAsset != null) 682 if (textureAsset != null)
@@ -659,9 +759,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
659 using (Bitmap img = (Bitmap)imgDecoder.DecodeToImage(asset)) 759 using (Bitmap img = (Bitmap)imgDecoder.DecodeToImage(asset))
660 ret = new warp_Texture(img); 760 ret = new warp_Texture(img);
661 } 761 }
662 catch (Exception e) 762 catch /*(Exception e)*/
663 { 763 {
664 m_log.Warn(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0}, exception ", id), e); 764 m_log.Debug(string.Format("[WARP 3D IMAGE MODULE]: Failed to decode asset {0}, exception ", id));
665 } 765 }
666 } 766 }
667 767
@@ -671,7 +771,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
671 #endregion Rendering Methods 771 #endregion Rendering Methods
672 772
673 #region Static Helpers 773 #region Static Helpers
674
675 // Note: axis change. 774 // Note: axis change.
676 private static warp_Vector ConvertVector(float x, float y, float z) 775 private static warp_Vector ConvertVector(float x, float y, float z)
677 { 776 {
@@ -725,10 +824,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
725 { 824 {
726 width = bitmap.Width; 825 width = bitmap.Width;
727 height = bitmap.Height; 826 height = bitmap.Height;
728 827
729 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); 828 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
730 pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; 829 pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
731 830
732 // Sum up the individual channels 831 // Sum up the individual channels
733 unsafe 832 unsafe
734 { 833 {
@@ -737,7 +836,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
737 for (int y = 0; y < height; y++) 836 for (int y = 0; y < height; y++)
738 { 837 {
739 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 838 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
740 839
741 for (int x = 0; x < width; x++) 840 for (int x = 0; x < width; x++)
742 { 841 {
743 b += row[x * pixelBytes + 0]; 842 b += row[x * pixelBytes + 0];
@@ -752,7 +851,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
752 for (int y = 0; y < height; y++) 851 for (int y = 0; y < height; y++)
753 { 852 {
754 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); 853 byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
755 854
756 for (int x = 0; x < width; x++) 855 for (int x = 0; x < width; x++)
757 { 856 {
758 b += row[x * pixelBytes + 0]; 857 b += row[x * pixelBytes + 0];
@@ -780,7 +879,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
780 } 879 }
781 catch (Exception ex) 880 catch (Exception ex)
782 { 881 {
783 m_log.WarnFormat( 882 m_log.DebugFormat(
784 "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", 883 "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}",
785 textureID, j2kData.Length, ex.Message); 884 textureID, j2kData.Length, ex.Message);
786 885
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
index 6af4050..a2b44df 100644
--- a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
50 private float m_avgDirection = 0.0f; // Average direction of the wind in degrees 50 private float m_avgDirection = 0.0f; // Average direction of the wind in degrees
51 private float m_varStrength = 5.0f; // Max Strength Variance 51 private float m_varStrength = 5.0f; // Max Strength Variance
52 private float m_varDirection = 30.0f;// Max Direction Variance 52 private float m_varDirection = 30.0f;// Max Direction Variance
53 private float m_rateChange = 1.0f; // 53 private float m_rateChange = 1.0f; //
54 54
55 private Vector2 m_curPredominateWind = new Vector2(); 55 private Vector2 m_curPredominateWind = new Vector2();
56 56
@@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
70 70
71 public void Initialise() 71 public void Initialise()
72 { 72 {
73 73
74 } 74 }
75 75
76 #endregion 76 #endregion
@@ -103,7 +103,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
103 } 103 }
104 } 104 }
105 105
106 public void WindUpdate(uint frame) 106 public bool WindUpdate(uint frame)
107 { 107 {
108 double avgAng = m_avgDirection * (Math.PI/180.0f); 108 double avgAng = m_avgDirection * (Math.PI/180.0f);
109 double varDir = m_varDirection * (Math.PI/180.0f); 109 double varDir = m_varDirection * (Math.PI/180.0f);
@@ -111,7 +111,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
111 // Prevailing wind algorithm 111 // Prevailing wind algorithm
112 // Inspired by Kanker Greenacre 112 // Inspired by Kanker Greenacre
113 113
114 // TODO: 114 // TODO:
115 // * This should probably be based on in-world time. 115 // * This should probably be based on in-world time.
116 // * should probably move all these local variables to class members and constants 116 // * should probably move all these local variables to class members and constants
117 double time = DateTime.Now.TimeOfDay.Seconds / 86400.0f; 117 double time = DateTime.Now.TimeOfDay.Seconds / 86400.0f;
@@ -125,10 +125,8 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
125 offset = Math.Sin(theta) * Math.Sin(theta*4) + (Math.Sin(theta*13) / 3); 125 offset = Math.Sin(theta) * Math.Sin(theta*4) + (Math.Sin(theta*13) / 3);
126 double windSpeed = m_avgStrength + (m_varStrength * offset); 126 double windSpeed = m_avgStrength + (m_varStrength * offset);
127 127
128 if (windSpeed<0) 128 if (windSpeed < 0)
129 windSpeed=0; 129 windSpeed = -windSpeed;
130
131
132 130
133 m_curPredominateWind.X = (float)Math.Cos(windDir); 131 m_curPredominateWind.X = (float)Math.Cos(windDir);
134 m_curPredominateWind.Y = (float)Math.Sin(windDir); 132 m_curPredominateWind.Y = (float)Math.Sin(windDir);
@@ -144,6 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
144 m_windSpeeds[y * 16 + x] = m_curPredominateWind; 142 m_windSpeeds[y * 16 + x] = m_curPredominateWind;
145 } 143 }
146 } 144 }
145 return true;
147 } 146 }
148 147
149 public Vector3 WindSpeed(float fX, float fY, float fZ) 148 public Vector3 WindSpeed(float fX, float fY, float fZ)
@@ -158,9 +157,9 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
158 157
159 public string Description 158 public string Description
160 { 159 {
161 get 160 get
162 { 161 {
163 return "Provides a predominate wind direction that can change within configured variances for direction and speed."; 162 return "Provides a predominate wind direction that can change within configured variances for direction and speed.";
164 } 163 }
165 } 164 }
166 165
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
index fcb0c10..d2ff7b3 100644
--- a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
@@ -82,22 +82,23 @@ namespace OpenSim.Region.CoreModules.World.Wind.Plugins
82 } 82 }
83 } 83 }
84 84
85 public void WindUpdate(uint frame) 85 public bool WindUpdate(uint frame)
86 { 86 {
87 //Make sure our object is valid (we haven't been disposed of yet) 87 //Make sure our object is valid (we haven't been disposed of yet)
88 if (m_windSpeeds != null) 88 if (m_windSpeeds == null)
89 return false;
90
91 for (int y = 0; y < 16; y++)
89 { 92 {
90 for (int y = 0; y < 16; y++) 93 for (int x = 0; x < 16; x++)
91 { 94 {
92 for (int x = 0; x < 16; x++) 95 m_windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1
93 { 96 m_windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1
94 m_windSpeeds[y * 16 + x].X = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 97 m_windSpeeds[y * 16 + x].X *= m_strength;
95 m_windSpeeds[y * 16 + x].Y = (float)(m_rndnums.NextDouble() * 2d - 1d); // -1 to 1 98 m_windSpeeds[y * 16 + x].Y *= m_strength;
96 m_windSpeeds[y * 16 + x].X *= m_strength;
97 m_windSpeeds[y * 16 + x].Y *= m_strength;
98 }
99 } 99 }
100 } 100 }
101 return true;
101 } 102 }
102 103
103 public Vector3 WindSpeed(float fX, float fY, float fZ) 104 public Vector3 WindSpeed(float fX, float fY, float fZ)
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index 35014f5..96ba003 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -46,11 +46,13 @@ namespace OpenSim.Region.CoreModules
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private uint m_frame = 0; 48 private uint m_frame = 0;
49 private uint m_frameLastUpdateClientArray = 0; 49 private int m_dataVersion = 0;
50// private int m_regionID = 0;
50 private int m_frameUpdateRate = 150; 51 private int m_frameUpdateRate = 150;
51 //private Random m_rndnums = new Random(Environment.TickCount); 52 //private Random m_rndnums = new Random(Environment.TickCount);
52 private Scene m_scene = null; 53 private Scene m_scene = null;
53 private bool m_ready = false; 54 private bool m_ready = false;
55 private bool m_inUpdate = false;
54 56
55 private bool m_enabled = false; 57 private bool m_enabled = false;
56 private IConfig m_windConfig; 58 private IConfig m_windConfig;
@@ -96,11 +98,10 @@ namespace OpenSim.Region.CoreModules
96 98
97 m_scene = scene; 99 m_scene = scene;
98 m_frame = 0; 100 m_frame = 0;
99
100 // Register all the Wind Model Plug-ins 101 // Register all the Wind Model Plug-ins
101 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule", false)) 102 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule", false))
102 { 103 {
103 m_log.InfoFormat("[WIND] Found Plugin: {0}", windPlugin.Name); 104 m_log.DebugFormat("[WIND] Found Plugin: {0}", windPlugin.Name);
104 m_availableWindPlugins.Add(windPlugin.Name, windPlugin); 105 m_availableWindPlugins.Add(windPlugin.Name, windPlugin);
105 } 106 }
106 107
@@ -109,7 +110,7 @@ namespace OpenSim.Region.CoreModules
109 { 110 {
110 m_activeWindPlugin = m_availableWindPlugins[m_dWindPluginName]; 111 m_activeWindPlugin = m_availableWindPlugins[m_dWindPluginName];
111 112
112 m_log.InfoFormat("[WIND] {0} plugin found, initializing.", m_dWindPluginName); 113 m_log.DebugFormat("[WIND] {0} plugin found, initializing.", m_dWindPluginName);
113 114
114 if (m_windConfig != null) 115 if (m_windConfig != null)
115 { 116 {
@@ -118,7 +119,6 @@ namespace OpenSim.Region.CoreModules
118 } 119 }
119 } 120 }
120 121
121
122 // if the plug-in wasn't found, default to no wind. 122 // if the plug-in wasn't found, default to no wind.
123 if (m_activeWindPlugin == null) 123 if (m_activeWindPlugin == null)
124 { 124 {
@@ -154,14 +154,14 @@ namespace OpenSim.Region.CoreModules
154 154
155 // Register event handlers for when Avatars enter the region, and frame ticks 155 // Register event handlers for when Avatars enter the region, and frame ticks
156 m_scene.EventManager.OnFrame += WindUpdate; 156 m_scene.EventManager.OnFrame += WindUpdate;
157 m_scene.EventManager.OnMakeRootAgent += OnAgentEnteredRegion;
158 157
159 // Register the wind module 158 // Register the wind module
160 m_scene.RegisterModuleInterface<IWindModule>(this); 159 m_scene.RegisterModuleInterface<IWindModule>(this);
161 160
162 // Generate initial wind values 161 // Generate initial wind values
163 GenWindPos(); 162 GenWind();
164 163 // hopefully this will not be the same for all regions on same instance
164 m_dataVersion = (int)m_scene.AllocateLocalId();
165 // Mark Module Ready for duty 165 // Mark Module Ready for duty
166 m_ready = true; 166 m_ready = true;
167 } 167 }
@@ -184,7 +184,7 @@ namespace OpenSim.Region.CoreModules
184 184
185 // Remove our hooks 185 // Remove our hooks
186 m_scene.EventManager.OnFrame -= WindUpdate; 186 m_scene.EventManager.OnFrame -= WindUpdate;
187 m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion; 187// m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion;
188 188
189 } 189 }
190 190
@@ -351,7 +351,7 @@ namespace OpenSim.Region.CoreModules
351 #region IWindModule Methods 351 #region IWindModule Methods
352 352
353 /// <summary> 353 /// <summary>
354 /// Retrieve the wind speed at the given region coordinate. This 354 /// Retrieve the wind speed at the given region coordinate. This
355 /// implimentation ignores Z. 355 /// implimentation ignores Z.
356 /// </summary> 356 /// </summary>
357 /// <param name="x">0...255</param> 357 /// <param name="x">0...255</param>
@@ -396,7 +396,7 @@ namespace OpenSim.Region.CoreModules
396 396
397 public string WindActiveModelPluginName 397 public string WindActiveModelPluginName
398 { 398 {
399 get 399 get
400 { 400 {
401 if (m_activeWindPlugin != null) 401 if (m_activeWindPlugin != null)
402 { 402 {
@@ -416,67 +416,43 @@ namespace OpenSim.Region.CoreModules
416 /// </summary> 416 /// </summary>
417 public void WindUpdate() 417 public void WindUpdate()
418 { 418 {
419 if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready) 419 if ((!m_ready || m_inUpdate || (m_frame++ % m_frameUpdateRate) != 0))
420 {
421 return; 420 return;
422 }
423
424 GenWindPos();
425
426 SendWindAllClients();
427 }
428 421
429 public void OnAgentEnteredRegion(ScenePresence avatar) 422 m_inUpdate = true;
430 { 423 Util.FireAndForget(delegate
431 if (m_ready)
432 { 424 {
433 if (m_activeWindPlugin != null) 425 try
434 { 426 {
435 // Ask wind plugin to generate a LL wind array to be cached locally 427 GenWind();
436 // Try not to update this too often, as it may involve array copies 428 m_scene.ForEachClient(delegate(IClientAPI client)
437 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
438 { 429 {
439 windSpeeds = m_activeWindPlugin.WindLLClientArray(); 430 client.SendWindData(m_dataVersion, windSpeeds);
440 m_frameLastUpdateClientArray = m_frame; 431 });
441 }
442 }
443
444 avatar.ControllingClient.SendWindData(windSpeeds);
445 }
446 }
447 432
448 private void SendWindAllClients() 433 }
449 { 434 finally
450 if (m_ready)
451 {
452 if (m_scene.GetRootAgentCount() > 0)
453 { 435 {
454 // Ask wind plugin to generate a LL wind array to be cached locally 436 m_inUpdate = false;
455 // Try not to update this too often, as it may involve array copies
456 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
457 {
458 windSpeeds = m_activeWindPlugin.WindLLClientArray();
459 m_frameLastUpdateClientArray = m_frame;
460 }
461
462 m_scene.ForEachRootClient(delegate(IClientAPI client)
463 {
464 client.SendWindData(windSpeeds);
465 });
466 } 437 }
467 } 438 },
439 null, "WindModuleUpdate");
468 } 440 }
441
469 /// <summary> 442 /// <summary>
470 /// Calculate the sun's orbital position and its velocity. 443 /// Calculate new wind
444 /// returns false if no change
471 /// </summary> 445 /// </summary>
472 446
473 private void GenWindPos() 447 private bool GenWind()
474 { 448 {
475 if (m_activeWindPlugin != null) 449 if (m_activeWindPlugin != null && m_activeWindPlugin.WindUpdate(m_frame))
476 { 450 {
477 // Tell Wind Plugin to update it's wind data 451 windSpeeds = m_activeWindPlugin.WindLLClientArray();
478 m_activeWindPlugin.WindUpdate(m_frame); 452 m_dataVersion++;
453 return true;
479 } 454 }
455 return false;
480 } 456 }
481 } 457 }
482} 458}
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index d862f18..5876df3 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -128,109 +128,116 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 m_Clients.Add(remoteClient.AgentId); 128 m_Clients.Add(remoteClient.AgentId);
129 } 129 }
130 130
131 try 131 OnMapNameRequest(remoteClient, mapName, flags);
132 {
133 OnMapNameRequest(remoteClient, mapName, flags);
134 }
135 finally
136 {
137 lock (m_Clients)
138 m_Clients.Remove(remoteClient.AgentId);
139 }
140 } 132 }
141 133
142 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 134 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
143 { 135 {
144 List<MapBlockData> blocks = new List<MapBlockData>(); 136 Util.FireAndForget(x =>
145 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
146 { 137 {
147 // final block, closing the search result 138 try
148 AddFinalBlock(blocks); 139 {
140 List<MapBlockData> blocks = new List<MapBlockData>();
141 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
142 {
143 // final block, closing the search result
144 AddFinalBlock(blocks,mapName);
149 145
150 // flags are agent flags sent from the viewer. 146 // flags are agent flags sent from the viewer.
151 // they have different values depending on different viewers, apparently 147 // they have different values depending on different viewers, apparently
152 remoteClient.SendMapBlock(blocks, flags); 148 remoteClient.SendMapBlock(blocks, flags);
153 remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); 149 remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
154 return; 150 return;
155 } 151 }
156 152
153 //m_log.DebugFormat("MAP NAME=({0})", mapName);
157 154
158 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); 155 // Hack to get around the fact that ll V3 now drops the port from the
159 156 // map name. See https://jira.secondlife.com/browse/VWR-28570
160 string mapNameOrig = mapName; 157 //
161 if (regionInfos.Count == 0) 158 // Caller, use this magic form instead:
162 { 159 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128
163 // Hack to get around the fact that ll V3 now drops the port from the 160 // or url encode if possible.
164 // map name. See https://jira.secondlife.com/browse/VWR-28570 161 // the hacks we do with this viewer...
165 // 162 //
166 // Caller, use this magic form instead: 163 bool needOriginalName = false;
167 // secondlife://http|!!mygrid.com|8002|Region+Name/128/128 164 string mapNameOrig = mapName;
168 // or url encode if possible. 165 if (mapName.Contains("|"))
169 // the hacks we do with this viewer...
170 //
171 if (mapName.Contains("|"))
172 mapName = mapName.Replace('|', ':');
173 if (mapName.Contains("+"))
174 mapName = mapName.Replace('+', ' ');
175 if (mapName.Contains("!"))
176 mapName = mapName.Replace('!', '/');
177
178 if (mapName != mapNameOrig)
179 regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
180 }
181
182 m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags);
183
184 if (regionInfos.Count > 0)
185 {
186 foreach (GridRegion info in regionInfos)
187 {
188 if ((flags & 2) == 2) // V2 sends this
189 { 166 {
190 List<MapBlockData> datas = WorldMap.Map2BlockFromGridRegion(info, flags); 167 mapName = mapName.Replace('|', ':');
191 // ugh! V2-3 is very sensitive about the result being 168 needOriginalName = true;
192 // exactly the same as the requested name
193 if (regionInfos.Count == 1 && (mapName != mapNameOrig))
194 datas.ForEach(d => d.Name = mapNameOrig);
195
196 blocks.AddRange(datas);
197 } 169 }
198 else 170 if (mapName.Contains("+"))
199 { 171 {
200 MapBlockData data = WorldMap.MapBlockFromGridRegion(info, flags); 172 mapName = mapName.Replace('+', ' ');
201 blocks.Add(data); 173 needOriginalName = true;
202 } 174 }
203 } 175 if (mapName.Contains("!"))
204 } 176 {
177 mapName = mapName.Replace('!', '/');
178 needOriginalName = true;
179 }
180 if (mapName.Contains("."))
181 needOriginalName = true;
205 182
206 // final block, closing the search result 183 // try to fetch from GridServer
207 AddFinalBlock(blocks); 184 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
185 // if (regionInfos.Count == 0)
186 // remoteClient.SendAlertMessage("Hyperlink could not be established.");
208 187
209 // flags are agent flags sent from the viewer. 188 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
210 // they have different values depending on different viewers, apparently
211 remoteClient.SendMapBlock(blocks, flags);
212 189
213 // send extra user messages for V3 190 MapBlockData data;
214 // because the UI is very confusing 191 if (regionInfos != null && regionInfos.Count > 0)
215 // while we don't fix the hard-coded urls 192 {
216 if (flags == 2) 193 foreach (GridRegion info in regionInfos)
217 { 194 {
218 if (regionInfos.Count == 0) 195 data = new MapBlockData();
219 remoteClient.SendAlertMessage("No regions found with that name."); 196 data.Agents = 0;
220 // this seems unnecessary because found regions will show up in the search results 197 data.Access = info.Access;
221 //else if (regionInfos.Count == 1) 198 MapBlockData block = new MapBlockData();
222 // remoteClient.SendAlertMessage("Region found!"); 199 WorldMap.MapBlockFromGridRegion(block, info, flags);
223 } 200
201 if (flags == 2 && regionInfos.Count == 1 && needOriginalName)
202 block.Name = mapNameOrig;
203 blocks.Add(block);
204 }
205 }
206
207 // final block, closing the search result
208 AddFinalBlock(blocks,mapNameOrig);
209
210 // flags are agent flags sent from the viewer.
211 // they have different values depending on different viewers, apparently
212 remoteClient.SendMapBlock(blocks, flags);
213
214 // send extra user messages for V3
215 // because the UI is very confusing
216 // while we don't fix the hard-coded urls
217 if (flags == 2)
218 {
219 if (regionInfos == null || regionInfos.Count == 0)
220 remoteClient.SendAgentAlertMessage("No regions found with that name.", true);
221 // else if (regionInfos.Count == 1)
222 // remoteClient.SendAgentAlertMessage("Region found!", false);
223 }
224 }
225 finally
226 {
227 lock (m_Clients)
228 m_Clients.Remove(remoteClient.AgentId);
229 }
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..94072a5 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -66,32 +66,34 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
66 66
67 private static readonly string DEFAULT_WORLD_MAP_EXPORT_PATH = "exportmap.jpg"; 67 private static readonly string DEFAULT_WORLD_MAP_EXPORT_PATH = "exportmap.jpg";
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
70 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
71
72 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
73 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
70 74
71 private IMapImageGenerator m_mapImageGenerator; 75 private IMapImageGenerator m_mapImageGenerator;
72 private IMapImageUploadModule m_mapImageServiceModule; 76 private IMapImageUploadModule m_mapImageServiceModule;
73 77
74 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
75
76 protected Scene m_scene; 78 protected Scene m_scene;
77 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 79 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; 80 private byte[] myMapImageJPEG;
81 protected volatile bool m_Enabled = false; 81 protected volatile bool m_Enabled = false;
82 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>(); 82 private ExpiringCache<string, int> m_blacklistedurls = new ExpiringCache<string, int>();
83 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 83 private ExpiringCache<ulong, int> m_blacklistedregions = new ExpiringCache<ulong, int>();
84 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 84 private ExpiringCache<ulong, string> m_cachedRegionMapItemsAddress = new ExpiringCache<ulong, string>();
85 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 85 private ExpiringCache<ulong, OSDMap> m_cachedRegionMapItemsResponses =
86 new ExpiringCache<ulong, OSDMap>();
86 private List<UUID> m_rootAgents = new List<UUID>(); 87 private List<UUID> m_rootAgents = new List<UUID>();
87 private volatile bool threadrunning = false; 88 private volatile bool threadrunning = false;
88 89 // expire time for the blacklists in seconds
89 private IServiceThrottleModule m_ServiceThrottle; 90 private double expireBlackListTime = 600.0; // 10 minutes
90 91 // expire mapItems responses time in seconds. Throttles requests to regions that do answer
92 private const double expireResponsesTime = 120.0; // 2 minutes ?
91 //private int CacheRegionsDistance = 256; 93 //private int CacheRegionsDistance = 256;
92 94
93 #region INonSharedRegionModule Members 95 #region INonSharedRegionModule Members
94 public virtual void Initialise (IConfigSource config) 96 public virtual void Initialise(IConfigSource config)
95 { 97 {
96 string[] configSections = new string[] { "Map", "Startup" }; 98 string[] configSections = new string[] { "Map", "Startup" };
97 99
@@ -99,8 +101,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
99 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") 101 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
100 m_Enabled = true; 102 m_Enabled = true;
101 103
102 blacklistTimeout 104 expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
103 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
104 } 105 }
105 106
106 public virtual void AddRegion(Scene scene) 107 public virtual void AddRegion(Scene scene)
@@ -128,7 +129,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 } 129 }
129 } 130 }
130 131
131 public virtual void RemoveRegion (Scene scene) 132 public virtual void RemoveRegion(Scene scene)
132 { 133 {
133 if (!m_Enabled) 134 if (!m_Enabled)
134 return; 135 return;
@@ -141,13 +142,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
141 } 142 }
142 } 143 }
143 144
144 public virtual void RegionLoaded (Scene scene) 145 public virtual void RegionLoaded(Scene scene)
145 { 146 {
146 if (!m_Enabled) 147 if (!m_Enabled)
147 return; 148 return;
148 149
149 m_ServiceThrottle = scene.RequestModuleInterface<IServiceThrottleModule>();
150
151 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>(); 150 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>();
152 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>(); 151 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>();
153 } 152 }
@@ -177,16 +176,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
177 regionimage = regionimage.Replace("-", ""); 176 regionimage = regionimage.Replace("-", "");
178 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage); 177 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage);
179 178
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*/
191
192 MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage);
190 MainServer.Instance.AddLLSDHandler( 193 MainServer.Instance.AddLLSDHandler(
191 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 194 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
192 195
@@ -197,13 +200,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
197 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; 200 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
198 m_scene.EventManager.OnRegionUp += OnRegionUp; 201 m_scene.EventManager.OnRegionUp += OnRegionUp;
199 202
200// StartThread(new object()); 203 StartThread(new object());
201 } 204 }
202 205
203 // this has to be called with a lock on m_scene 206 // this has to be called with a lock on m_scene
204 protected virtual void RemoveHandlers() 207 protected virtual void RemoveHandlers()
205 { 208 {
206// StopThread(); 209 StopThread();
207 210
208 m_scene.EventManager.OnRegionUp -= OnRegionUp; 211 m_scene.EventManager.OnRegionUp -= OnRegionUp;
209 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent; 212 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent;
@@ -212,6 +215,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
212 m_scene.EventManager.OnNewClient -= OnNewClient; 215 m_scene.EventManager.OnNewClient -= OnNewClient;
213 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 216 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
214 217
218 m_scene.UnregisterModuleInterface<IWorldMapModule>(this);
219
215 string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); 220 string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString();
216 regionimage = regionimage.Replace("-", ""); 221 regionimage = regionimage.Replace("-", "");
217 MainServer.Instance.RemoveLLSDHandler("/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), 222 MainServer.Instance.RemoveLLSDHandler("/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(),
@@ -222,12 +227,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
222 public void OnRegisterCaps(UUID agentID, Caps caps) 227 public void OnRegisterCaps(UUID agentID, Caps caps)
223 { 228 {
224 //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 229 //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
225 string capsBase = "/CAPS/" + caps.CapsObjectPath; 230 string capspath = "/CAPS/" + UUID.Random();
226 caps.RegisterHandler( 231 caps.RegisterHandler(
227 "MapLayer", 232 "MapLayer",
228 new RestStreamHandler( 233 new RestStreamHandler(
229 "POST", 234 "POST",
230 capsBase + m_mapLayerPath, 235 capspath,
231 (request, path, param, httpRequest, httpResponse) 236 (request, path, param, httpRequest, httpResponse)
232 => MapLayerRequest(request, path, param, agentID, caps), 237 => MapLayerRequest(request, path, param, agentID, caps),
233 "MapLayer", 238 "MapLayer",
@@ -246,6 +251,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
246 public string MapLayerRequest(string request, string path, string param, 251 public string MapLayerRequest(string request, string path, string param,
247 UUID agentID, Caps caps) 252 UUID agentID, Caps caps)
248 { 253 {
254 // not sure about this....
255
249 //try 256 //try
250 // 257 //
251 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", 258 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
@@ -261,54 +268,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 268 // 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. 269 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
263 270
264 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 271 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
265 { 272 //{
266 ScenePresence avatarPresence = null; 273 // ScenePresence avatarPresence = null;
267 274
268 m_scene.TryGetScenePresence(agentID, out avatarPresence); 275 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
269 276
270 if (avatarPresence != null) 277 // if (avatarPresence != null)
271 { 278 // {
272 bool lookup = false; 279 // bool lookup = false;
273 280
274 lock (cachedMapBlocks) 281 // lock (cachedMapBlocks)
275 { 282 // {
276 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 283 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
277 { 284 // {
278 List<MapBlockData> mapBlocks; 285 // List<MapBlockData> mapBlocks;
279 286
280 mapBlocks = cachedMapBlocks; 287 // mapBlocks = cachedMapBlocks;
281 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 288 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
282 } 289 // }
283 else 290 // else
284 { 291 // {
285 lookup = true; 292 // lookup = true;
286 } 293 // }
287 } 294 // }
288 if (lookup) 295 // if (lookup)
289 { 296 // {
290 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 297 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
291 298
292 // Get regions that are within 8 regions of here 299 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
293 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 300 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
294 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 8), 301 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
295 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 8), 302 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
296 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 8), 303 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
297 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 8) ); 304 // foreach (GridRegion r in regions)
298 foreach (GridRegion r in regions) 305 // {
299 { 306 // MapBlockData block = new MapBlockData();
300 MapBlockData block = MapBlockFromGridRegion(r, 0); 307 // MapBlockFromGridRegion(block, r, 0);
301 mapBlocks.Add(block); 308 // mapBlocks.Add(block);
302 } 309 // }
303 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 310 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
304 311
305 lock (cachedMapBlocks) 312 // lock (cachedMapBlocks)
306 cachedMapBlocks = mapBlocks; 313 // cachedMapBlocks = mapBlocks;
307 314
308 cachedTime = Util.UnixTimeSinceEpoch(); 315 // cachedTime = Util.UnixTimeSinceEpoch();
309 } 316 // }
310 } 317 // }
311 } 318 //}
312 319
313 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 320 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
314 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 321 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -334,9 +341,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
334 /// <returns></returns> 341 /// <returns></returns>
335 protected static OSDMapLayer GetOSDMapLayerResponse() 342 protected static OSDMapLayer GetOSDMapLayerResponse()
336 { 343 {
344 // not sure about this.... 2048 or master 5000 and hack above?
345
337 OSDMapLayer mapLayer = new OSDMapLayer(); 346 OSDMapLayer mapLayer = new OSDMapLayer();
338 mapLayer.Right = 5000; 347 mapLayer.Right = 2048;
339 mapLayer.Top = 5000; 348 mapLayer.Top = 2048;
340 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 349 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
341 350
342 return mapLayer; 351 return mapLayer;
@@ -365,6 +374,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
365 { 374 {
366 m_rootAgents.Remove(AgentId); 375 m_rootAgents.Remove(AgentId);
367 } 376 }
377 lock (m_mapBlockRequestEvent)
378 {
379 if (m_mapBlockRequests.ContainsKey(AgentId))
380 m_mapBlockRequests.Remove(AgentId);
381 }
368 } 382 }
369 #endregion 383 #endregion
370 384
@@ -379,14 +393,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
379 if (threadrunning) return; 393 if (threadrunning) return;
380 threadrunning = true; 394 threadrunning = true;
381 395
382// m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread"); 396 // m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread");
383 397
384 WorkManager.StartThread( 398 WorkManager.StartThread(
385 process, 399 process,
386 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName), 400 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName),
387 ThreadPriority.BelowNormal, 401 ThreadPriority.BelowNormal,
388 true, 402 true,
389 true); 403 false);
404 WorkManager.StartThread(
405 MapBlockSendThread,
406 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
407 ThreadPriority.BelowNormal,
408 true,
409 false);
390 } 410 }
391 411
392 /// <summary> 412 /// <summary>
@@ -396,13 +416,29 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
396 { 416 {
397 MapRequestState st = new MapRequestState(); 417 MapRequestState st = new MapRequestState();
398 st.agentID = STOP_UUID; 418 st.agentID = STOP_UUID;
399 st.EstateID=0; 419 st.EstateID = 0;
400 st.flags=0; 420 st.flags = 0;
401 st.godlike=false; 421 st.godlike = false;
402 st.itemtype=0; 422 st.itemtype = 0;
403 st.regionhandle=0; 423 st.regionhandle = 0;
404 424
405 requests.Enqueue(st); 425 requests.Enqueue(st);
426
427 MapBlockRequestData req = new MapBlockRequestData();
428
429 req.client = null;
430 req.minX = 0;
431 req.maxX = 0;
432 req.minY = 0;
433 req.maxY = 0;
434 req.flags = 0;
435
436 lock (m_mapBlockRequestEvent)
437 {
438 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
439 m_mapBlockRequests[UUID.Zero].Enqueue(req);
440 m_mapBlockRequestEvent.Set();
441 }
406 } 442 }
407 443
408 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 444 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -415,315 +451,371 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
415 if (!m_rootAgents.Contains(remoteClient.AgentId)) 451 if (!m_rootAgents.Contains(remoteClient.AgentId))
416 return; 452 return;
417 } 453 }
454
455 // local or remote request?
456 if (regionhandle != 0 && regionhandle != m_scene.RegionInfo.RegionHandle)
457 {
458 // its Remote Map Item Request
459 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes.
460 RequestMapItems("", remoteClient.AgentId, flags, EstateID, godlike, itemtype, regionhandle);
461 return;
462 }
463
418 uint xstart = 0; 464 uint xstart = 0;
419 uint ystart = 0; 465 uint ystart = 0;
420 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); 466 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
421 if (itemtype == (int)GridItemType.AgentLocations) 467
468 // its about this region...
469
470 List<mapItemReply> mapitems = new List<mapItemReply>();
471 mapItemReply mapitem = new mapItemReply();
472
473 // viewers only ask for green dots to each region now
474 // except at login with regionhandle 0
475 // possible on some other rare ocasions
476 // use previus hack of sending all items with the green dots
477
478 bool adultRegion;
479 if (regionhandle == 0)
422 { 480 {
423 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 481 switch (itemtype)
424 { 482 {
425 // Just requesting map info about the current, local region 483 case (int)GridItemType.AgentLocations:
426 int tc = Environment.TickCount; 484 // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
427 List<mapItemReply> mapitems = new List<mapItemReply>(); 485
428 mapItemReply mapitem = new mapItemReply(); 486 int tc = Environment.TickCount;
429 if (m_scene.GetRootAgentCount() <= 1) 487 if (m_scene.GetRootAgentCount() <= 1)
430 { 488 {
431 mapitem = new mapItemReply( 489 mapitem = new mapItemReply(
432 xstart + 1, 490 xstart + 1,
433 ystart + 1, 491 ystart + 1,
434 UUID.Zero, 492 UUID.Zero,
435 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 493 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
436 0, 0); 494 0, 0);
437 mapitems.Add(mapitem); 495 mapitems.Add(mapitem);
438 } 496 }
439 else 497 else
440 {
441 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
442 { 498 {
499 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
500 {
443 // Don't send a green dot for yourself 501 // Don't send a green dot for yourself
444 if (sp.UUID != remoteClient.AgentId) 502 if (sp.UUID != remoteClient.AgentId)
445 { 503 {
446 mapitem = new mapItemReply( 504 mapitem = new mapItemReply(
447 xstart + (uint)sp.AbsolutePosition.X, 505 xstart + (uint)sp.AbsolutePosition.X,
448 ystart + (uint)sp.AbsolutePosition.Y, 506 ystart + (uint)sp.AbsolutePosition.Y,
449 UUID.Zero, 507 UUID.Zero,
450 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 508 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
451 1, 0); 509 1, 0);
452 mapitems.Add(mapitem); 510 mapitems.Add(mapitem);
453 } 511 }
454 }); 512 });
455 } 513 }
456 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 514 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
457 } 515 break;
458 else
459 {
460 // Remote Map Item Request
461 516
462 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 517 case (int)GridItemType.Telehub:
463 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 518 // Service 1 (MAP_ITEM_TELEHUB)
464 } 519
465 } 520 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
466 else if (itemtype == (int)GridItemType.LandForSale) // Service 7 (MAP_ITEM_LAND_FOR_SALE) 521 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 { 522 {
481 // Play it safe 523 mapitem = new mapItemReply(
482 if (!(parcel_interface is LandObject)) 524 xstart + (uint)sog.AbsolutePosition.X,
483 continue; 525 ystart + (uint)sog.AbsolutePosition.Y,
526 UUID.Zero,
527 sog.Name,
528 0, // color (not used)
529 0 // 0 = telehub / 1 = infohub
530 );
531 mapitems.Add(mapitem);
532 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
533 }
534 break;
484 535
485 LandObject land = (LandObject)parcel_interface; 536 case (int)GridItemType.AdultLandForSale:
486 LandData parcel = land.LandData; 537 case (int)GridItemType.LandForSale:
487 538
488 // Show land for sale 539 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
489 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale) 540 adultRegion = m_scene.RegionInfo.RegionSettings.Maturity == 2;
490 { 541 if (adultRegion)
491 Vector3 min = parcel.AABBMin; 542 {
492 Vector3 max = parcel.AABBMax; 543 if (itemtype == (int)GridItemType.LandForSale)
493 float x = (min.X+max.X)/2; 544 break;
494 float y = (min.Y+max.Y)/2; 545 }
546 else
547 {
548 if (itemtype == (int)GridItemType.AdultLandForSale)
549 break;
550 }
495 551
496 mapitem = new mapItemReply( 552 // Parcels
553 ILandChannel landChannel = m_scene.LandChannel;
554 List<ILandObject> parcels = landChannel.AllParcels();
555
556 if ((parcels != null) && (parcels.Count >= 1))
557 {
558 foreach (ILandObject parcel_interface in parcels)
559 {
560 // Play it safe
561 if (!(parcel_interface is LandObject))
562 continue;
563
564 LandObject land = (LandObject)parcel_interface;
565 LandData parcel = land.LandData;
566
567 // Show land for sale
568 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
569 {
570 Vector3 min = parcel.AABBMin;
571 Vector3 max = parcel.AABBMax;
572 float x = (min.X + max.X) / 2;
573 float y = (min.Y + max.Y) / 2;
574 mapitem = new mapItemReply(
497 xstart + (uint)x, 575 xstart + (uint)x,
498 ystart + (uint)y, 576 ystart + (uint)y,
499 parcel.GlobalID, 577 parcel.GlobalID,
500 parcel.Name, 578 parcel.Name,
501 parcel.Area, 579 parcel.Area,
502 parcel.SalePrice 580 parcel.SalePrice
503 ); 581 );
504 mapitems.Add(mapitem); 582 mapitems.Add(mapitem);
583 }
505 } 584 }
506 } 585 }
507 } 586 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
508 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 587 break;
509 }
510 else
511 {
512 // Remote Map Item Request
513 588
514 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 589 case (uint)GridItemType.PgEvent:
515 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 590 case (uint)GridItemType.MatureEvent:
591 case (uint)GridItemType.AdultEvent:
592 case (uint)GridItemType.Classified:
593 case (uint)GridItemType.Popular:
594 // TODO
595 // just dont not cry about them
596 break;
597
598 default:
599 // unkown map item type
600 m_log.DebugFormat("[WORLD MAP]: Unknown MapItem type {1}", itemtype);
601 break;
516 } 602 }
517 } 603 }
518 else if (itemtype == (int)GridItemType.Telehub) // Service 1 (MAP_ITEM_TELEHUB) 604 else
519 { 605 {
520 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 606 // send all items till we get a better fix
521 {
522 List<mapItemReply> mapitems = new List<mapItemReply>();
523 mapItemReply mapitem = new mapItemReply();
524 607
525 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject); 608 // 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 609
538 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 610 int tc = Environment.TickCount;
539 } 611 if (m_scene.GetRootAgentCount() <= 1)
612 {
613 mapitem = new mapItemReply(
614 xstart + 1,
615 ystart + 1,
616 UUID.Zero,
617 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
618 0, 0);
619 mapitems.Add(mapitem);
540 } 620 }
541 else 621 else
542 { 622 {
543 // Remote Map Item Request 623 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
544 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 624 {
625 // Don't send a green dot for yourself
626 if (sp.UUID != remoteClient.AgentId)
627 {
628 mapitem = new mapItemReply(
629 xstart + (uint)sp.AbsolutePosition.X,
630 ystart + (uint)sp.AbsolutePosition.Y,
631 UUID.Zero,
632 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
633 1, 0);
634 mapitems.Add(mapitem);
635 }
636 });
545 } 637 }
546 } 638 remoteClient.SendMapItemReply(mapitems.ToArray(), 6, flags);
547 } 639 mapitems.Clear();
548 640
549 private int nAsyncRequests = 0; 641 // Service 1 (MAP_ITEM_TELEHUB)
550 /// <summary> 642
551 /// Processing thread main() loop for doing remote mapitem requests 643 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
552 /// </summary> 644 if (sog != null)
553 public void process()
554 {
555 //const int MAX_ASYNC_REQUESTS = 20;
556 try
557 {
558 while (true)
559 { 645 {
560 MapRequestState st = requests.Dequeue(1000); 646 mapitem = new mapItemReply(
647 xstart + (uint)sog.AbsolutePosition.X,
648 ystart + (uint)sog.AbsolutePosition.Y,
649 UUID.Zero,
650 sog.Name,
651 0, // color (not used)
652 0 // 0 = telehub / 1 = infohub
653 );
654 mapitems.Add(mapitem);
655 remoteClient.SendMapItemReply(mapitems.ToArray(), 1, flags);
656 mapitems.Clear();
657 }
561 658
562 // end gracefully 659 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
563 if (st.agentID == STOP_UUID)
564 break;
565 660
566 if (st.agentID != UUID.Zero) 661 uint its = 7;
662 if (m_scene.RegionInfo.RegionSettings.Maturity == 2)
663 its = 10;
664
665 // Parcels
666 ILandChannel landChannel = m_scene.LandChannel;
667 List<ILandObject> parcels = landChannel.AllParcels();
668
669 if ((parcels != null) && (parcels.Count >= 1))
670 {
671 foreach (ILandObject parcel_interface in parcels)
567 { 672 {
568 bool dorequest = true; 673 // Play it safe
569 lock (m_rootAgents) 674 if (!(parcel_interface is LandObject))
570 { 675 continue;
571 if (!m_rootAgents.Contains(st.agentID)) 676
572 dorequest = false; 677 LandObject land = (LandObject)parcel_interface;
573 } 678 LandData parcel = land.LandData;
574 679
575 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 680 // Show land for sale
681 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
576 { 682 {
577 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 683 Vector3 min = parcel.AABBMin;
578 Thread.Sleep(80); 684 Vector3 max = parcel.AABBMax;
579 685 float x = (min.X + max.X) / 2;
580 RequestMapItemsDelegate d = RequestMapItemsAsync; 686 float y = (min.Y + max.Y) / 2;
581 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); 687 mapitem = new mapItemReply(
582 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); 688 xstart + (uint)x,
583 //RequestMapItemsCompleted(response); 689 ystart + (uint)y,
584 Interlocked.Increment(ref nAsyncRequests); 690 parcel.GlobalID,
691 parcel.Name,
692 parcel.Area,
693 parcel.SalePrice
694 );
695 mapitems.Add(mapitem);
585 } 696 }
586 } 697 }
587 698 if(mapitems.Count >0)
588 Watchdog.UpdateThread(); 699 remoteClient.SendMapItemReply(mapitems.ToArray(), its, flags);
700 mapitems.Clear();
589 } 701 }
590 } 702 }
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 } 703 }
599 704
600 const int MAX_ASYNC_REQUESTS = 20; 705 private int nAsyncRequests = 0;
601
602 /// <summary> 706 /// <summary>
603 /// Enqueues the map item request into the services throttle processing thread 707 /// Processing thread main() loop for doing remote mapitem requests
604 /// </summary> 708 /// </summary>
605 /// <param name="state"></param> 709 public void process()
606 public void EnqueueMapItemRequest(MapRequestState st)
607 { 710 {
711 const int MAX_ASYNC_REQUESTS = 20;
712 ScenePresence av = null;
713 MapRequestState st = null;
608 714
609 m_ServiceThrottle.Enqueue("map-item", st.regionhandle.ToString() + st.agentID.ToString(), delegate 715 try
610 { 716 {
611 if (st.agentID != UUID.Zero) 717 while (true)
612 { 718 {
613 bool dorequest = true; 719 av = null;
614 lock (m_rootAgents) 720 st = null;
615 {
616 if (!m_rootAgents.Contains(st.agentID))
617 dorequest = false;
618 }
619 721
620 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 722 st = requests.Dequeue(4500);
621 { 723 Watchdog.UpdateThread();
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 724
630 RequestMapItemsDelegate d = RequestMapItemsAsync; 725 if (st == null || st.agentID == UUID.Zero)
631 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); 726 continue;
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 727
640 /// <summary> 728 // end gracefully
641 /// Sends the mapitem response to the IClientAPI 729 if (st.agentID == STOP_UUID)
642 /// </summary> 730 break;
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 731
649 OSDMap response = (OSDMap)icon.EndInvoke(iar); 732 // agent gone?
650 733
651 Interlocked.Decrement(ref nAsyncRequests); 734 m_scene.TryGetScenePresence(st.agentID, out av);
735 if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
736 continue;
652 737
653 if (!response.ContainsKey("requestID")) 738 // region unreachable?
654 return; 739 if (m_blacklistedregions.Contains(st.regionhandle))
740 continue;
655 741
656 UUID requestID = response["requestID"].AsUUID(); 742 bool dorequest = true;
743 OSDMap responseMap = null;
657 744
658 if (requestID != UUID.Zero) 745 // check if we are already serving this region
659 { 746 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 { 747 {
666 mrs = m_openRequests[requestID]; 748 if (m_cachedRegionMapItemsResponses.Contains(st.regionhandle))
667 m_openRequests.Remove(requestID); 749 {
750 m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out responseMap);
751 dorequest = false;
752 }
753 else
754 m_cachedRegionMapItemsResponses.Add(st.regionhandle, null, expireResponsesTime); // a bit more time for the access
668 } 755 }
669 }
670 756
671 if (mrs.agentID != UUID.Zero) 757 if (dorequest)
672 {
673 ScenePresence av = null;
674 m_scene.TryGetScenePresence(mrs.agentID, out av);
675 if (av != null)
676 { 758 {
677 if (response.ContainsKey(mrs.itemtype.ToString())) 759 // nothig for region, fire a request
760 Interlocked.Increment(ref nAsyncRequests);
761 MapRequestState rst = st;
762 Util.FireAndForget(x =>
678 { 763 {
679 List<mapItemReply> returnitems = new List<mapItemReply>(); 764 RequestMapItemsAsync(rst.agentID, rst.flags, rst.EstateID, rst.godlike, rst.itemtype, rst.regionhandle);
680 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; 765 });
681 for (int i = 0; i < itemarray.Count; i++) 766 }
682 { 767 else
683 OSDMap mapitem = (OSDMap)itemarray[i]; 768 {
684 mapItemReply mi = new mapItemReply(); 769 // do we have the response?
685 mi.FromOSD(mapitem); 770 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 { 771 {
696 List<mapItemReply> returnitems = new List<mapItemReply>(); 772 if(av!=null)
697 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
698 for (int i = 0; i < itemarray.Count; i++)
699 { 773 {
700 OSDMap mapitem = (OSDMap)itemarray[i]; 774 // this will mainly only send green dots now
701 mapItemReply mi = new mapItemReply(); 775 if (responseMap.ContainsKey(st.itemtype.ToString()))
702 mi.FromOSD(mapitem); 776 {
703 returnitems.Add(mi); 777 List<mapItemReply> returnitems = new List<mapItemReply>();
778 OSDArray itemarray = (OSDArray)responseMap[st.itemtype.ToString()];
779 for (int i = 0; i < itemarray.Count; i++)
780 {
781 OSDMap mapitem = (OSDMap)itemarray[i];
782 mapItemReply mi = new mapItemReply();
783 mi.x = (uint)mapitem["X"].AsInteger();
784 mi.y = (uint)mapitem["Y"].AsInteger();
785 mi.id = mapitem["ID"].AsUUID();
786 mi.Extra = mapitem["Extra"].AsInteger();
787 mi.Extra2 = mapitem["Extra2"].AsInteger();
788 mi.name = mapitem["Name"].AsString();
789 returnitems.Add(mi);
790 }
791 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), st.itemtype, st.flags & 0xffff);
792 }
704 } 793 }
705 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
706 } 794 }
707 795 else
708 // Service 1 (MAP_ITEM_TELEHUB)
709 itemtype = (uint)GridItemType.Telehub;
710
711 if (response.ContainsKey(itemtype.ToString()))
712 { 796 {
713 List<mapItemReply> returnitems = new List<mapItemReply>(); 797 // request still beeing processed, enqueue it back
714 OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; 798 requests.Enqueue(st);
715 for (int i = 0; i < itemarray.Count; i++) 799 if (requests.Count() < 3)
716 { 800 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 } 801 }
724 } 802 }
803
804 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
805 {
806 Thread.Sleep(100);
807 Watchdog.UpdateThread();
808 }
725 } 809 }
726 } 810 }
811
812 catch (Exception e)
813 {
814 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
815 }
816
817 threadrunning = false;
818 Watchdog.RemoveThread();
727 } 819 }
728 820
729 /// <summary> 821 /// <summary>
@@ -746,11 +838,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
746 st.godlike = godlike; 838 st.godlike = godlike;
747 st.itemtype = itemtype; 839 st.itemtype = itemtype;
748 st.regionhandle = regionhandle; 840 st.regionhandle = regionhandle;
749 EnqueueMapItemRequest(st); 841
842 requests.Enqueue(st);
750 } 843 }
751 844
752 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags, 845 uint[] itemTypesForcedSend = new uint[] { 6, 1, 7, 10 }; // green dots, infohub, land sells
753 uint EstateID, bool godlike, uint itemtype, ulong regionhandle); 846
754 /// <summary> 847 /// <summary>
755 /// Does the actual remote mapitem request 848 /// Does the actual remote mapitem request
756 /// This should be called from an asynchronous thread 849 /// This should be called from an asynchronous thread
@@ -765,94 +858,55 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
765 /// <param name="itemtype">passed in from packet</param> 858 /// <param name="itemtype">passed in from packet</param>
766 /// <param name="regionhandle">Region we're looking up</param> 859 /// <param name="regionhandle">Region we're looking up</param>
767 /// <returns></returns> 860 /// <returns></returns>
768 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 861 private void RequestMapItemsAsync(UUID id, uint flags,
769 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 862 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
770 { 863 {
771// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 864 // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
772 865
773 string httpserver = ""; 866 string httpserver = "";
774 bool blacklisted = false; 867 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 868
783 m_blacklistedregions.Remove(regionhandle); 869 lock (m_blacklistedregions)
784 } 870 blacklisted = m_blacklistedregions.Contains(regionhandle);
785 else
786 blacklisted = true;
787 }
788 }
789 871
790 if (blacklisted) 872 if (blacklisted)
791 return new OSDMap(); 873 {
874 Interlocked.Decrement(ref nAsyncRequests);
875 return;
876 }
792 877
793 UUID requestID = UUID.Random(); 878 UUID requestID = UUID.Random();
794 lock (m_cachedRegionMapItemsAddress) 879 lock (m_cachedRegionMapItemsAddress)
795 { 880 m_cachedRegionMapItemsAddress.TryGetValue(regionhandle, out httpserver);
796 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 881
797 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 882 if (httpserver == null || httpserver.Length == 0)
798 }
799 if (httpserver.Length == 0)
800 { 883 {
801 uint x = 0, y = 0; 884 uint x = 0, y = 0;
802 Util.RegionHandleToWorldLoc(regionhandle, out x, out y); 885 Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
886
803 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 887 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
804 888
805 if (mreg != null) 889 if (mreg != null)
806 { 890 {
807 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); 891 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString();
808 lock (m_cachedRegionMapItemsAddress) 892 lock (m_cachedRegionMapItemsAddress)
809 { 893 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 } 894 }
823 } 895 }
824 896
825 blacklisted = false;
826 lock (m_blacklistedurls) 897 lock (m_blacklistedurls)
827 { 898 {
828 if (m_blacklistedurls.ContainsKey(httpserver)) 899 if (httpserver == null || httpserver.Length == 0 || m_blacklistedurls.Contains(httpserver))
829 { 900 {
830 if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) 901 // Can't find the http server or its blocked
831 { 902 lock (m_blacklistedregions)
832 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver); 903 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
833 904
834 m_blacklistedurls.Remove(httpserver); 905 Interlocked.Decrement(ref nAsyncRequests);
835 } 906 return;
836 else
837 blacklisted = true;
838 } 907 }
839 } 908 }
840 909
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; 910 WebRequest mapitemsrequest = null;
857 try 911 try
858 { 912 {
@@ -861,132 +915,144 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
861 catch (Exception e) 915 catch (Exception e)
862 { 916 {
863 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 917 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
864 return new OSDMap(); 918 Interlocked.Decrement(ref nAsyncRequests);
919 return;
865 } 920 }
866 921
867 mapitemsrequest.Method = "POST"; 922 mapitemsrequest.Method = "POST";
868 mapitemsrequest.ContentType = "application/xml+llsd"; 923 mapitemsrequest.ContentType = "application/xml+llsd";
869 OSDMap RAMap = new OSDMap();
870 924
925 OSDMap RAMap = new OSDMap();
871 // string RAMapString = RAMap.ToString(); 926 // string RAMapString = RAMap.ToString();
872 OSD LLSDofRAMap = RAMap; // RENAME if this works 927 OSD LLSDofRAMap = RAMap; // RENAME if this works
873 928
874 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); 929 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
930
875 OSDMap responseMap = new OSDMap(); 931 OSDMap responseMap = new OSDMap();
876 responseMap["requestID"] = OSD.FromUUID(requestID);
877 932
878 Stream os = null;
879 try 933 try
880 { // send the Post 934 { // send the Post
881 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send 935 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
882 os = mapitemsrequest.GetRequestStream(); 936 using (Stream os = mapitemsrequest.GetRequestStream())
883 os.Write(buffer, 0, buffer.Length); //Send it 937 os.Write(buffer, 0, buffer.Length); //Send it
884 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver); 938 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver);
885 } 939 }
886 catch (WebException ex) 940 catch (WebException ex)
887 { 941 {
888 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 942 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
889 responseMap["connect"] = OSD.FromBoolean(false); 943 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
890 lock (m_blacklistedurls) 944 lock (m_blacklistedurls)
891 { 945 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
892 if (!m_blacklistedurls.ContainsKey(httpserver)) 946 lock (m_blacklistedregions)
893 m_blacklistedurls.Add(httpserver, Environment.TickCount); 947 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
894 }
895
896 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
897 948
898 return responseMap; 949 Interlocked.Decrement(ref nAsyncRequests);
950 return;
899 } 951 }
900 catch 952 catch
901 { 953 {
902 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 954 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
903 responseMap["connect"] = OSD.FromBoolean(false); 955 Interlocked.Decrement(ref nAsyncRequests);
904 return responseMap; 956 return;
905 }
906 finally
907 {
908 if (os != null)
909 os.Dispose();
910 } 957 }
911 958
912 string response_mapItems_reply = null; 959 string response_mapItems_reply = null;
913 { 960 { // get the response
914 try 961 try
915 { 962 {
916 using (WebResponse webResponse = mapitemsrequest.GetResponse()) 963 using (WebResponse webResponse = mapitemsrequest.GetResponse())
917 { 964 {
918 if (webResponse != null) 965 if (webResponse != null)
919 { 966 {
920 using (Stream s = webResponse.GetResponseStream()) 967 using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
921 using (StreamReader sr = new StreamReader(s)) 968 {
922 response_mapItems_reply = sr.ReadToEnd().Trim(); 969 response_mapItems_reply = sr.ReadToEnd().Trim();
970 }
923 } 971 }
924 else 972 else
925 { 973 {
926 return new OSDMap(); 974 Interlocked.Decrement(ref nAsyncRequests);
927 } 975 return;
928 } 976 }
977 }
929 } 978 }
930 catch (WebException) 979 catch (WebException)
931 { 980 {
932 responseMap["connect"] = OSD.FromBoolean(false);
933 lock (m_blacklistedurls) 981 lock (m_blacklistedurls)
934 { 982 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
935 if (!m_blacklistedurls.ContainsKey(httpserver)) 983 lock (m_blacklistedregions)
936 m_blacklistedurls.Add(httpserver, Environment.TickCount); 984 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
937 }
938 985
939 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 986 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
940 987
941 return responseMap; 988 Interlocked.Decrement(ref nAsyncRequests);
989 return;
942 } 990 }
943 catch 991 catch
944 { 992 {
945 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 993 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
946 responseMap["connect"] = OSD.FromBoolean(false);
947 lock (m_blacklistedregions) 994 lock (m_blacklistedregions)
948 { 995 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
949 if (!m_blacklistedregions.ContainsKey(regionhandle))
950 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
951 }
952 996
953 return responseMap; 997 Interlocked.Decrement(ref nAsyncRequests);
998 return;
954 } 999 }
955 1000
956 OSD rezResponse = null;
957 try 1001 try
958 { 1002 {
959 rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply); 1003 responseMap = (OSDMap)OSDParser.DeserializeLLSDXml(response_mapItems_reply);
960
961 responseMap = (OSDMap)rezResponse;
962 responseMap["requestID"] = OSD.FromUUID(requestID);
963 } 1004 }
964 catch (Exception ex) 1005 catch (Exception ex)
965 { 1006 {
966 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 1007 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) 1008 lock (m_blacklistedregions)
970 { 1009 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
971 if (!m_blacklistedregions.ContainsKey(regionhandle))
972 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
973 }
974 1010
975 return responseMap; 1011 Interlocked.Decrement(ref nAsyncRequests);
1012 return;
976 } 1013 }
977 } 1014 }
978 1015
979 if (!responseMap.ContainsKey(itemtype.ToString())) // remote sim doesnt have the stated region handle 1016 // cache the response that may include other valid items
1017 lock (m_cachedRegionMapItemsResponses)
1018 m_cachedRegionMapItemsResponses.AddOrUpdate(regionhandle, responseMap, expireResponsesTime);
1019
1020 flags &= 0xffff;
1021
1022 if (id != UUID.Zero)
980 { 1023 {
981 m_log.DebugFormat("[WORLD MAP]: Remote sim does not have the stated region. Blacklisting."); 1024 ScenePresence av = null;
982 lock (m_blacklistedregions) 1025 m_scene.TryGetScenePresence(id, out av);
1026 if (av != null && !av.IsChildAgent && !av.IsDeleted && !av.IsInTransit)
983 { 1027 {
984 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1028 // send all the items or viewers will never ask for them, except green dots
985 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 1029 foreach (uint itfs in itemTypesForcedSend)
1030 {
1031 if (responseMap.ContainsKey(itfs.ToString()))
1032 {
1033 List<mapItemReply> returnitems = new List<mapItemReply>();
1034// OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
1035 OSDArray itemarray = (OSDArray)responseMap[itfs.ToString()];
1036 for (int i = 0; i < itemarray.Count; i++)
1037 {
1038 OSDMap mapitem = (OSDMap)itemarray[i];
1039 mapItemReply mi = new mapItemReply();
1040 mi.x = (uint)mapitem["X"].AsInteger();
1041 mi.y = (uint)mapitem["Y"].AsInteger();
1042 mi.id = mapitem["ID"].AsUUID();
1043 mi.Extra = mapitem["Extra"].AsInteger();
1044 mi.Extra2 = mapitem["Extra2"].AsInteger();
1045 mi.name = mapitem["Name"].AsString();
1046 returnitems.Add(mi);
1047 }
1048// av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
1049 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itfs, flags);
1050 }
1051 }
986 } 1052 }
987 } 1053 }
988 1054
989 return responseMap; 1055 Interlocked.Decrement(ref nAsyncRequests);
990 } 1056 }
991 1057
992 /// <summary> 1058 /// <summary>
@@ -996,87 +1062,196 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
996 /// <param name="minY"></param> 1062 /// <param name="minY"></param>
997 /// <param name="maxX"></param> 1063 /// <param name="maxX"></param>
998 /// <param name="maxY"></param> 1064 /// <param name="maxY"></param>
999 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1065 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1066 {
1067// m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
1068
1069 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1070 }
1071
1072 private const double SPAMBLOCKTIMEms = 300000; // 5 minutes
1073 private Dictionary<UUID,double> spamBlocked = new Dictionary<UUID,double>();
1074
1075 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1000 { 1076 {
1001 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 1077 // anti spam because of FireStorm 4.7.7 absurd request repeat rates
1078 // possible others
1079
1080 double now = Util.GetTimeStampMS();
1081 UUID agentID = remoteClient.AgentId;
1082
1083 lock (m_mapBlockRequestEvent)
1002 { 1084 {
1003 List<MapBlockData> response = new List<MapBlockData>(); 1085 if(spamBlocked.ContainsKey(agentID))
1004
1005 // this should return one mapblock at most. It is triggered by a click
1006 // on an unloaded square.
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 { 1086 {
1016 foreach (GridRegion r in regions) 1087 if(spamBlocked[agentID] < now &&
1088 (!m_mapBlockRequests.ContainsKey(agentID) ||
1089 m_mapBlockRequests[agentID].Count == 0 ))
1017 { 1090 {
1018 if (r.RegionLocX == Util.RegionToWorldLoc((uint)minX) 1091 spamBlocked.Remove(agentID);
1019 && r.RegionLocY == Util.RegionToWorldLoc((uint)minY) ) 1092 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", agentID);
1093 }
1094 else
1095 return new List<MapBlockData>();
1096 }
1097 else
1098 {
1099 // ugly slow expire spammers
1100 if(spamBlocked.Count > 0)
1101 {
1102 UUID k = UUID.Zero;
1103 bool expireone = false;
1104 foreach(UUID k2 in spamBlocked.Keys)
1020 { 1105 {
1021 // found it => add it to response 1106 if(spamBlocked[k2] < now &&
1022 // Version 2 viewers can handle the larger regions 1107 (!m_mapBlockRequests.ContainsKey(k2) ||
1023 if ((flag & 2) == 2) 1108 m_mapBlockRequests[k2].Count == 0 ))
1024 response.AddRange(Map2BlockFromGridRegion(r, flag)); 1109 {
1025 else 1110 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", k2);
1026 response.Add(MapBlockFromGridRegion(r, flag)); 1111 k = k2;
1027 break; 1112 expireone = true;
1113 }
1114 break; // doing one at a time
1028 } 1115 }
1116 if(expireone)
1117 spamBlocked.Remove(k);
1029 } 1118 }
1030 } 1119 }
1031 1120
1032 if (response.Count == 0) 1121// m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
1122
1123 MapBlockRequestData req = new MapBlockRequestData();
1124
1125 req.client = remoteClient;
1126 req.minX = minX;
1127 req.maxX = maxX;
1128 req.minY = minY;
1129 req.maxY = maxY;
1130 req.flags = flag;
1131
1132 if (!m_mapBlockRequests.ContainsKey(agentID))
1133 m_mapBlockRequests[agentID] = new Queue<MapBlockRequestData>();
1134 if(m_mapBlockRequests[agentID].Count < 150 )
1135 m_mapBlockRequests[agentID].Enqueue(req);
1136 else
1033 { 1137 {
1034 // response still empty => couldn't find the map-tile the user clicked on => tell the client 1138 spamBlocked[agentID] = now + SPAMBLOCKTIMEms;
1035 MapBlockData block = new MapBlockData(); 1139 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks blocking spammer {0} for {1} s",agentID, SPAMBLOCKTIMEms/1000.0);
1036 block.X = (ushort)minX;
1037 block.Y = (ushort)minY;
1038 block.Access = (byte)SimAccess.Down; // means 'simulator is offline'
1039 // block.Access = (byte)SimAccess.NonExistent;
1040 response.Add(block);
1041 } 1140 }
1042 // The lower 16 bits are an unsigned int16 1141 m_mapBlockRequestEvent.Set();
1043 remoteClient.SendMapBlock(response, flag & 0xffff);
1044 } 1142 }
1045 else 1143
1144 return new List<MapBlockData>();
1145 }
1146
1147 protected void MapBlockSendThread()
1148 {
1149 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1150 while (true)
1046 { 1151 {
1047 // normal mapblock request. Use the provided values 1152 while(!m_mapBlockRequestEvent.WaitOne(4900))
1048 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); 1153 {
1154 Watchdog.UpdateThread();
1155 if(m_scene == null)
1156 return;
1157 }
1158 Watchdog.UpdateThread();
1159 lock (m_mapBlockRequestEvent)
1160 {
1161 int total = 0;
1162 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
1163 {
1164 if (q.Count > 0)
1165 thisRunData.Add(q.Dequeue());
1166
1167 total += q.Count;
1168 }
1169
1170 if (total == 0)
1171 m_mapBlockRequestEvent.Reset();
1172 }
1173
1174 if(thisRunData.Count > 0)
1175 {
1176 foreach (MapBlockRequestData req in thisRunData)
1177 {
1178 // Null client stops thread
1179 if (req.client == null)
1180 return;
1181
1182 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
1183 }
1184
1185 thisRunData.Clear();
1186 }
1187
1188 Thread.Sleep(50);
1049 } 1189 }
1050 } 1190 }
1051 1191
1052 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1192 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1053 { 1193 {
1194 List<MapBlockData> allBlocks = new List<MapBlockData>();
1054 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1195 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1055 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1196 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1056 (int)Util.RegionToWorldLoc((uint)(minX - 4)), (int)Util.RegionToWorldLoc((uint)(maxX + 4)), 1197 minX * (int)Constants.RegionSize,
1057 (int)Util.RegionToWorldLoc((uint)(minY - 4)), (int)Util.RegionToWorldLoc((uint)(maxY + 4)) ); 1198 maxX * (int)Constants.RegionSize,
1058 //m_log.DebugFormat("{0} GetAndSendBlocks. min=<{1},{2}>, max=<{3},{4}>, cntFound={5}", 1199 minY * (int)Constants.RegionSize,
1059 // LogHeader, minX, minY, maxX, maxY, regions.Count); 1200 maxY * (int)Constants.RegionSize);
1201
1202 // only send a negative answer for a single region request
1203 // corresponding to a click on the map. Current viewers
1204 // keep displaying "loading.." without this
1205 if (regions.Count == 0 && (flag & 0x10000) != 0 && minX == maxX && minY == maxY)
1206 {
1207 MapBlockData block = new MapBlockData();
1208 block.X = (ushort)minX;
1209 block.Y = (ushort)minY;
1210 block.MapImageId = UUID.Zero;
1211 block.Access = (byte)SimAccess.NonExistent;
1212 allBlocks.Add(block);
1213 mapBlocks.Add(block);
1214 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1215 return allBlocks;
1216 }
1217
1218 flag &= 0xffff;
1219
1060 foreach (GridRegion r in regions) 1220 foreach (GridRegion r in regions)
1061 { 1221 {
1062 // Version 2 viewers can handle the larger regions 1222 if (r == null)
1063 if ((flag & 2) == 2) 1223 continue;
1064 mapBlocks.AddRange(Map2BlockFromGridRegion(r, flag)); 1224 MapBlockData block = new MapBlockData();
1065 else 1225 MapBlockFromGridRegion(block, r, flag);
1066 mapBlocks.Add(MapBlockFromGridRegion(r, flag)); 1226 mapBlocks.Add(block);
1227 allBlocks.Add(block);
1228
1229 if (mapBlocks.Count >= 10)
1230 {
1231 remoteClient.SendMapBlock(mapBlocks, flag);
1232 mapBlocks.Clear();
1233 Thread.Sleep(50);
1234 }
1067 } 1235 }
1068 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1236 if (mapBlocks.Count > 0)
1237 remoteClient.SendMapBlock(mapBlocks, flag);
1069 1238
1070 return mapBlocks; 1239 return allBlocks;
1071 } 1240 }
1072 1241
1073 // Fill a passed MapBlockData from a GridRegion 1242 public void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
1074 public MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag)
1075 { 1243 {
1076 MapBlockData block = new MapBlockData(); 1244 if (r == null)
1245 {
1246 // we should not get here ??
1247// block.Access = (byte)SimAccess.Down; this is for a grid reply on r
1248 block.Access = (byte)SimAccess.NonExistent;
1249 block.MapImageId = UUID.Zero;
1250 return;
1251 }
1077 1252
1078 block.Access = r.Access; 1253 block.Access = r.Access;
1079 switch (flag & 0xffff) 1254 switch (flag)
1080 { 1255 {
1081 case 0: 1256 case 0:
1082 block.MapImageId = r.TerrainImage; 1257 block.MapImageId = r.TerrainImage;
@@ -1089,50 +1264,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1089 break; 1264 break;
1090 } 1265 }
1091 block.Name = r.RegionName; 1266 block.Name = r.RegionName;
1092 block.X = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocX); 1267 block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
1093 block.Y = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocY); 1268 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1094 block.SizeX = (ushort) r.RegionSizeX; 1269 block.SizeX = (ushort)r.RegionSizeX;
1095 block.SizeY = (ushort) r.RegionSizeY; 1270 block.SizeY = (ushort)r.RegionSizeY;
1096
1097 return block;
1098 }
1099 1271
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 } 1272 }
1134 1273
1135
1136 public Hashtable OnHTTPThrottled(Hashtable keysvals) 1274 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1137 { 1275 {
1138 Hashtable reply = new Hashtable(); 1276 Hashtable reply = new Hashtable();
@@ -1145,67 +1283,71 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1145 1283
1146 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1284 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1147 { 1285 {
1148 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1149 Hashtable reply = new Hashtable(); 1286 Hashtable reply = new Hashtable();
1150 int statuscode = 200; 1287 int statuscode = 200;
1151 byte[] jpeg = new byte[0]; 1288 byte[] jpeg = new byte[0];
1152 1289
1153 if (myMapImageJPEG.Length == 0) 1290 if (m_scene.RegionInfo.RegionSettings.TerrainImageID != UUID.Zero)
1154 { 1291 {
1155 MemoryStream imgstream = null; 1292 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 1293
1160 try 1294 if (myMapImageJPEG.Length == 0)
1161 { 1295 {
1162 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data 1296 MemoryStream imgstream = null;
1297 Bitmap mapTexture = new Bitmap(1, 1);
1298 ManagedImage managedImage;
1299 Image image = (Image)mapTexture;
1163 1300
1164 imgstream = new MemoryStream(); 1301 try
1302 {
1303 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
1165 1304
1166 // non-async because we know we have the asset immediately. 1305 imgstream = new MemoryStream();
1167 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1168 1306
1169 // Decode image to System.Drawing.Image 1307 // non-async because we know we have the asset immediately.
1170 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) 1308 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1171 {
1172 // Save to bitmap
1173 mapTexture = new Bitmap(image);
1174 1309
1175 EncoderParameters myEncoderParameters = new EncoderParameters(); 1310 // Decode image to System.Drawing.Image
1176 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); 1311 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
1312 {
1313 // Save to bitmap
1314 mapTexture = new Bitmap(image);
1177 1315
1178 // Save bitmap to stream 1316 EncoderParameters myEncoderParameters = new EncoderParameters();
1179 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters); 1317 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
1180 1318
1181 // Write the stream to a byte array for output 1319 // Save bitmap to stream
1182 jpeg = imgstream.ToArray(); 1320 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
1183 myMapImageJPEG = jpeg; 1321
1322 // Write the stream to a byte array for output
1323 jpeg = imgstream.ToArray();
1324 myMapImageJPEG = jpeg;
1325 }
1184 } 1326 }
1185 } 1327 catch (Exception)
1186 catch (Exception) 1328 {
1187 { 1329 // Dummy!
1188 // Dummy! 1330 m_log.Warn("[WORLD MAP]: Unable to generate Map image");
1189 m_log.Warn("[WORLD MAP]: Unable to generate Map image"); 1331 }
1190 } 1332 finally
1191 finally 1333 {
1192 { 1334 // Reclaim memory, these are unmanaged resources
1193 // Reclaim memory, these are unmanaged resources 1335 // 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 1336 if (mapTexture != null)
1195 if (mapTexture != null) 1337 mapTexture.Dispose();
1196 mapTexture.Dispose();
1197 1338
1198 if (image != null) 1339 if (image != null)
1199 image.Dispose(); 1340 image.Dispose();
1200 1341
1201 if (imgstream != null) 1342 if (imgstream != null)
1202 imgstream.Dispose(); 1343 imgstream.Dispose();
1344 }
1345 }
1346 else
1347 {
1348 // Use cached version so we don't have to loose our mind
1349 jpeg = myMapImageJPEG;
1203 } 1350 }
1204 }
1205 else
1206 {
1207 // Use cached version so we don't have to loose our mind
1208 jpeg = myMapImageJPEG;
1209 } 1351 }
1210 1352
1211 reply["str_response_string"] = Convert.ToBase64String(jpeg); 1353 reply["str_response_string"] = Convert.ToBase64String(jpeg);
@@ -1267,22 +1409,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1267 1409
1268 foreach (GridRegion r in regions) 1410 foreach (GridRegion r in regions)
1269 { 1411 {
1270 MapBlockData mapBlock = MapBlockFromGridRegion(r, 0); 1412 MapBlockData mapBlock = new MapBlockData();
1413 MapBlockFromGridRegion(mapBlock, r, 0);
1271 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString()); 1414 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1272 1415
1273 if (texAsset != null) 1416 if (texAsset != null)
1274 { 1417 {
1275 textures.Add(texAsset); 1418 textures.Add(texAsset);
1276 } 1419 }
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 } 1420 }
1287 1421
1288 foreach (AssetBase asset in textures) 1422 foreach (AssetBase asset in textures)
@@ -1308,6 +1442,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1308 1442
1309 mapTexture.Save(exportPath, ImageFormat.Jpeg); 1443 mapTexture.Save(exportPath, ImageFormat.Jpeg);
1310 1444
1445 g.Dispose();
1446 mapTexture.Dispose();
1447 sea.Dispose();
1448
1311 m_log.InfoFormat( 1449 m_log.InfoFormat(
1312 "[WORLD MAP]: Successfully exported world map for {0} to {1}", 1450 "[WORLD MAP]: Successfully exported world map for {0} to {1}",
1313 m_scene.RegionInfo.RegionName, exportPath); 1451 m_scene.RegionInfo.RegionName, exportPath);
@@ -1320,17 +1458,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1320 if (consoleScene != null && consoleScene != m_scene) 1458 if (consoleScene != null && consoleScene != m_scene)
1321 return; 1459 return;
1322 1460
1323 if (m_mapImageGenerator == null) 1461 GenerateMaptileForce();
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 } 1462 }
1335 1463
1336 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1464 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
@@ -1338,9 +1466,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1338 uint xstart = 0; 1466 uint xstart = 0;
1339 uint ystart = 0; 1467 uint ystart = 0;
1340 1468
1341 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); 1469 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 1470
1345 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots) 1471 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)
1346 1472
@@ -1362,8 +1488,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1362 } 1488 }
1363 else 1489 else
1364 { 1490 {
1365 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1491 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1366 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1492 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
1367 { 1493 {
1368 OSDMap responsemapdata = new OSDMap(); 1494 OSDMap responsemapdata = new OSDMap();
1369 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X)); 1495 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X));
@@ -1377,28 +1503,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1377 responsemap["6"] = responsearr; 1503 responsemap["6"] = responsearr;
1378 } 1504 }
1379 1505
1380 // Service 7 (MAP_ITEM_LAND_FOR_SALE) 1506 // Service 7/10 (MAP_ITEM_LAND_FOR_SALE/ADULT)
1381 1507
1382 ILandChannel landChannel = m_scene.LandChannel; 1508 ILandChannel landChannel = m_scene.LandChannel;
1383 List<ILandObject> parcels = landChannel.AllParcels(); 1509 List<ILandObject> parcels = landChannel.AllParcels();
1384 1510
1385 if ((parcels == null) || (parcels.Count == 0)) 1511 if ((parcels != null) && (parcels.Count >= 0))
1386 {
1387 OSDMap responsemapdata = new OSDMap();
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 { 1512 {
1401 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1513 OSDArray responsearr = new OSDArray(parcels.Count);
1402 foreach (ILandObject parcel_interface in parcels) 1514 foreach (ILandObject parcel_interface in parcels)
1403 { 1515 {
1404 // Play it safe 1516 // Play it safe
@@ -1413,8 +1525,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1413 { 1525 {
1414 Vector3 min = parcel.AABBMin; 1526 Vector3 min = parcel.AABBMin;
1415 Vector3 max = parcel.AABBMax; 1527 Vector3 max = parcel.AABBMax;
1416 float x = (min.X+max.X)/2; 1528 float x = (min.X + max.X) / 2;
1417 float y = (min.Y+max.Y)/2; 1529 float y = (min.Y + max.Y) / 2;
1418 1530
1419 OSDMap responsemapdata = new OSDMap(); 1531 OSDMap responsemapdata = new OSDMap();
1420 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x)); 1532 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x));
@@ -1427,7 +1539,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1427 responsearr.Add(responsemapdata); 1539 responsearr.Add(responsemapdata);
1428 } 1540 }
1429 } 1541 }
1430 responsemap["7"] = responsearr; 1542
1543 if(responsearr.Count > 0)
1544 {
1545 if(m_scene.RegionInfo.RegionSettings.Maturity == 2)
1546 responsemap["10"] = responsearr;
1547 else
1548 responsemap["7"] = responsearr;
1549 }
1431 } 1550 }
1432 1551
1433 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero) 1552 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
@@ -1453,61 +1572,138 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1453 return responsemap; 1572 return responsemap;
1454 } 1573 }
1455 1574
1575 private void GenerateMaptileForce()
1576 {
1577 // Cannot create a map for a nonexistent heightmap
1578 if (m_scene.Heightmap == null)
1579 return;
1580
1581 if (m_mapImageGenerator == null)
1582 {
1583 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1584 return;
1585 }
1586 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name);
1587
1588 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTileForce())
1589 {
1590 GenerateMaptile(mapbmp);
1591
1592 if (m_mapImageServiceModule != null)
1593 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1594 }
1595 }
1596
1456 public void GenerateMaptile() 1597 public void GenerateMaptile()
1457 { 1598 {
1458 // Cannot create a map for a nonexistent heightmap 1599 // Cannot create a map for a nonexistent heightmap
1459 if (m_scene.Heightmap == null) 1600 if (m_scene.Heightmap == null)
1460 return; 1601 return;
1461 1602
1603 if (m_mapImageGenerator == null)
1604 {
1605 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1606 return;
1607 }
1462 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name); 1608 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name);
1463 1609
1464 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile()) 1610 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1465 { 1611 {
1466 // V1 (This Module)
1467 GenerateMaptile(mapbmp); 1612 GenerateMaptile(mapbmp);
1468 1613
1469 // v2/3 (MapImageServiceModule) 1614 if (m_mapImageServiceModule != null)
1470 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp); 1615 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1471 } 1616 }
1472 } 1617 }
1473 1618
1474 private void GenerateMaptile(Bitmap mapbmp) 1619 private void GenerateMaptile(Bitmap mapbmp)
1475 { 1620 {
1476 byte[] data; 1621 bool needRegionSave = false;
1477 1622
1478 try 1623 // remove old assets
1624 UUID lastID = m_scene.RegionInfo.RegionSettings.TerrainImageID;
1625 if (lastID != UUID.Zero)
1479 { 1626 {
1480 data = OpenJPEG.EncodeFromImage(mapbmp, true); 1627 m_scene.AssetService.Delete(lastID.ToString());
1628 m_scene.RegionInfo.RegionSettings.TerrainImageID = UUID.Zero;
1629 myMapImageJPEG = new byte[0];
1630 needRegionSave = true;
1481 } 1631 }
1482 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke 1632
1633 lastID = m_scene.RegionInfo.RegionSettings.ParcelImageID;
1634 if (lastID != UUID.Zero)
1483 { 1635 {
1484 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e); 1636 m_scene.AssetService.Delete(lastID.ToString());
1485 return; 1637 m_scene.RegionInfo.RegionSettings.ParcelImageID = UUID.Zero;
1638 needRegionSave = true;
1486 } 1639 }
1487 1640
1488 byte[] overlay = GenerateOverlay(); 1641 if(mapbmp != null)
1642 {
1643 try
1644 {
1645 byte[] data;
1489 1646
1490 UUID terrainImageID = UUID.Random(); 1647 // if large region limit its size since new viewers will not use it
1491 UUID parcelImageID = UUID.Zero; 1648 // but it is still usable for ossl
1649 if(m_scene.RegionInfo.RegionSizeX > Constants.RegionSize ||
1650 m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1651 {
1652 int bx = mapbmp.Width;
1653 int by = mapbmp.Height;
1654 int mb = bx;
1655 if(mb < by)
1656 mb = by;
1657 if(mb > Constants.RegionSize && mb > 0)
1658 {
1659 float scale = (float)Constants.RegionSize/(float)mb;
1660 Size newsize = new Size();
1661 newsize.Width = (int)(bx * scale);
1662 newsize.Height = (int)(by * scale);
1492 1663
1493 AssetBase asset = new AssetBase( 1664 using(Bitmap scaledbmp = new Bitmap(mapbmp,newsize))
1494 terrainImageID, 1665 data = OpenJPEG.EncodeFromImage(scaledbmp, true);
1495 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(), 1666 }
1496 (sbyte)AssetType.Texture, 1667 else
1497 m_scene.RegionInfo.RegionID.ToString()); 1668 data = OpenJPEG.EncodeFromImage(mapbmp, true);
1498 asset.Data = data; 1669 }
1499 asset.Description = m_scene.RegionInfo.RegionName; 1670 else
1500 asset.Temporary = false; 1671 data = OpenJPEG.EncodeFromImage(mapbmp, true);
1501 asset.Flags = AssetFlags.Maptile;
1502 1672
1503 // Store the new one 1673 if (data != null && data.Length > 0)
1504 m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName); 1674 {
1505 1675 UUID terrainImageID = UUID.Random();
1506 m_scene.AssetService.Store(asset); 1676
1677 AssetBase asset = new AssetBase(
1678 terrainImageID,
1679 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(),
1680 (sbyte)AssetType.Texture,
1681 m_scene.RegionInfo.RegionID.ToString());
1682 asset.Data = data;
1683 asset.Description = m_scene.RegionInfo.RegionName;
1684 asset.Temporary = false;
1685 asset.Flags = AssetFlags.Maptile;
1686
1687 // Store the new one
1688 m_log.DebugFormat("[WORLD MAP]: Storing map image {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
1689
1690 m_scene.AssetService.Store(asset);
1691
1692 m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID;
1693 needRegionSave = true;
1694 }
1695 }
1696 catch (Exception e)
1697 {
1698 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e);
1699 }
1700 }
1507 1701
1702 // V2/3 still seem to need this, or we are missing something somewhere
1703 byte[] overlay = GenerateOverlay();
1508 if (overlay != null) 1704 if (overlay != null)
1509 { 1705 {
1510 parcelImageID = UUID.Random(); 1706 UUID parcelImageID = UUID.Random();
1511 1707
1512 AssetBase parcels = new AssetBase( 1708 AssetBase parcels = new AssetBase(
1513 parcelImageID, 1709 parcelImageID,
@@ -1520,20 +1716,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1520 parcels.Flags = AssetFlags.Maptile; 1716 parcels.Flags = AssetFlags.Maptile;
1521 1717
1522 m_scene.AssetService.Store(parcels); 1718 m_scene.AssetService.Store(parcels);
1719
1720 m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID;
1721 needRegionSave = true;
1523 } 1722 }
1524 1723
1525 // Switch to the new one 1724 if (needRegionSave)
1526 UUID lastTerrainImageID = m_scene.RegionInfo.RegionSettings.TerrainImageID; 1725 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 } 1726 }
1538 1727
1539 private void MakeRootAgent(ScenePresence avatar) 1728 private void MakeRootAgent(ScenePresence avatar)
@@ -1553,6 +1742,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1553 { 1742 {
1554 m_rootAgents.Remove(avatar.UUID); 1743 m_rootAgents.Remove(avatar.UUID);
1555 } 1744 }
1745
1746 lock (m_mapBlockRequestEvent)
1747 {
1748 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1749 m_mapBlockRequests.Remove(avatar.UUID);
1750 }
1556 } 1751 }
1557 1752
1558 public void OnRegionUp(GridRegion otherRegion) 1753 public void OnRegionUp(GridRegion otherRegion)
@@ -1562,46 +1757,67 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1562 1757
1563 lock (m_blacklistedregions) 1758 lock (m_blacklistedregions)
1564 { 1759 {
1565 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1760 if (m_blacklistedregions.Contains(regionhandle))
1566 m_blacklistedregions.Remove(regionhandle); 1761 m_blacklistedregions.Remove(regionhandle);
1567 } 1762 }
1568 1763
1569 lock (m_blacklistedurls) 1764 lock (m_blacklistedurls)
1570 { 1765 {
1571 if (m_blacklistedurls.ContainsKey(httpserver)) 1766 if (m_blacklistedurls.Contains(httpserver))
1572 m_blacklistedurls.Remove(httpserver); 1767 m_blacklistedurls.Remove(httpserver);
1573 } 1768 }
1574 1769
1575 lock (m_cachedRegionMapItemsAddress) 1770 lock (m_cachedRegionMapItemsAddress)
1576 { 1771 {
1577 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 1772 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle,
1578 m_cachedRegionMapItemsAddress.Remove(regionhandle); 1773 httpserver, 5.0 * expireBlackListTime);
1579 } 1774 }
1580 } 1775 }
1581 1776
1582 private Byte[] GenerateOverlay() 1777 private Byte[] GenerateOverlay()
1583 { 1778 {
1779 int landTileSize = LandManagementModule.LandUnit;
1780
1584 // These need to be ints for bitmap generation 1781 // These need to be ints for bitmap generation
1585 int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX; 1782 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; 1783 int regionLandTilesX = regionSizeX / landTileSize;
1784
1785 int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
1590 int regionLandTilesY = regionSizeY / landTileSize; 1786 int regionLandTilesY = regionSizeY / landTileSize;
1591 1787
1592 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY)) 1788 bool landForSale = false;
1789 ILandObject land;
1790
1791 // scan terrain avoiding potencial merges of large bitmaps
1792 //TODO create the sell bitmap at landchannel / landmaster ?
1793 // and auction also, still not suported
1794
1795 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY];
1796 for (int x = 0, xx = 0; x < regionLandTilesX; x++ ,xx += landTileSize)
1593 { 1797 {
1594 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY]; 1798 for (int y = 0, yy = 0; y < regionLandTilesY; y++, yy += landTileSize)
1595 for (int x = 0; x < regionLandTilesX; x++)
1596 { 1799 {
1597 for (int y = 0; y < regionLandTilesY; y++) 1800 land = m_scene.LandChannel.GetLandObject(xx, yy);
1801 if (land != null && (land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1802 {
1803 saleBitmap[x, y] = true;
1804 landForSale = true;
1805 }
1806 else
1598 saleBitmap[x, y] = false; 1807 saleBitmap[x, y] = false;
1599 } 1808 }
1809 }
1600 1810
1601 bool landForSale = false; 1811 if (!landForSale)
1812 {
1813 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1814 return null;
1815 }
1602 1816
1603 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); 1817 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1604 1818
1819 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY))
1820 {
1605 Color background = Color.FromArgb(0, 0, 0, 0); 1821 Color background = Color.FromArgb(0, 0, 0, 0);
1606 1822
1607 using (Graphics g = Graphics.FromImage(overlay)) 1823 using (Graphics g = Graphics.FromImage(overlay))
@@ -1609,36 +1825,19 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1609 using (SolidBrush transparent = new SolidBrush(background)) 1825 using (SolidBrush transparent = new SolidBrush(background))
1610 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY); 1826 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY);
1611 1827
1612 foreach (ILandObject land in parcels) 1828 // make it a bit transparent
1613 { 1829 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(192, 249, 223, 9)))
1614 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1615 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1616 {
1617 landForSale = true;
1618
1619 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
1620 }
1621 }
1622
1623 if (!landForSale)
1624 { 1830 {
1625 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName); 1831 for (int x = 0; x < regionLandTilesX; x++)
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 { 1832 {
1635 for (int y = 0 ; y < regionLandTilesY ; y++) 1833 for (int y = 0; y < regionLandTilesY; y++)
1636 { 1834 {
1637 if (saleBitmap[x, y]) 1835 if (saleBitmap[x, y])
1638 g.FillRectangle( 1836 g.FillRectangle(
1639 yellow, x * landTileSize, 1837 yellow,
1640 regionSizeX - landTileSize - (y * landTileSize), 1838 x * landTileSize,
1641 landTileSize, 1839 regionSizeX - landTileSize - (y * landTileSize),
1840 landTileSize,
1642 landTileSize); 1841 landTileSize);
1643 } 1842 }
1644 } 1843 }
@@ -1659,7 +1858,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1659 } 1858 }
1660 } 1859 }
1661 1860
1662 public struct MapRequestState 1861 public class MapRequestState
1663 { 1862 {
1664 public UUID agentID; 1863 public UUID agentID;
1665 public uint flags; 1864 public uint flags;
@@ -1668,4 +1867,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1668 public uint itemtype; 1867 public uint itemtype;
1669 public ulong regionhandle; 1868 public ulong regionhandle;
1670 } 1869 }
1870
1871 public struct MapBlockRequestData
1872 {
1873 public IClientAPI client;
1874 public int minX;
1875 public int minY;
1876 public int maxX;
1877 public int maxY;
1878 public uint flags;
1879 }
1671} 1880}