From 180be7de07014aa33bc6066f12a0819b731c1c9d Mon Sep 17 00:00:00 2001 From: Dr Scofield Date: Tue, 10 Feb 2009 13:10:57 +0000 Subject: this is step 2 of 2 of the OpenSim.Region.Environment refactor. NOTHING has been deleted or moved off to forge at this point. what has happened is that OpenSim.Region.Environment.Modules has been split in two: - OpenSim.Region.CoreModules: all those modules that are either directly or indirectly referenced from other OpenSim packages, or that provide functionality that the OpenSim developer community considers core functionality: CoreModules/Agent/AssetTransaction CoreModules/Agent/Capabilities CoreModules/Agent/TextureDownload CoreModules/Agent/TextureSender CoreModules/Agent/TextureSender/Tests CoreModules/Agent/Xfer CoreModules/Avatar/AvatarFactory CoreModules/Avatar/Chat/ChatModule CoreModules/Avatar/Combat CoreModules/Avatar/Currency/SampleMoney CoreModules/Avatar/Dialog CoreModules/Avatar/Friends CoreModules/Avatar/Gestures CoreModules/Avatar/Groups CoreModules/Avatar/InstantMessage CoreModules/Avatar/Inventory CoreModules/Avatar/Inventory/Archiver CoreModules/Avatar/Inventory/Transfer CoreModules/Avatar/Lure CoreModules/Avatar/ObjectCaps CoreModules/Avatar/Profiles CoreModules/Communications/Local CoreModules/Communications/REST CoreModules/Framework/EventQueue CoreModules/Framework/InterfaceCommander CoreModules/Hypergrid CoreModules/InterGrid CoreModules/Scripting/DynamicTexture CoreModules/Scripting/EMailModules CoreModules/Scripting/HttpRequest CoreModules/Scripting/LoadImageURL CoreModules/Scripting/VectorRender CoreModules/Scripting/WorldComm CoreModules/Scripting/XMLRPC CoreModules/World/Archiver CoreModules/World/Archiver/Tests CoreModules/World/Estate CoreModules/World/Land CoreModules/World/Permissions CoreModules/World/Serialiser CoreModules/World/Sound CoreModules/World/Sun CoreModules/World/Terrain CoreModules/World/Terrain/DefaultEffects CoreModules/World/Terrain/DefaultEffects/bin CoreModules/World/Terrain/DefaultEffects/bin/Debug CoreModules/World/Terrain/Effects CoreModules/World/Terrain/FileLoaders CoreModules/World/Terrain/FloodBrushes CoreModules/World/Terrain/PaintBrushes CoreModules/World/Terrain/Tests CoreModules/World/Vegetation CoreModules/World/Wind CoreModules/World/WorldMap - OpenSim.Region.OptionalModules: all those modules that are not core modules: OptionalModules/Avatar/Chat/IRC-stuff OptionalModules/Avatar/Concierge OptionalModules/Avatar/Voice/AsterixVoice OptionalModules/Avatar/Voice/SIPVoice OptionalModules/ContentManagementSystem OptionalModules/Grid/Interregion OptionalModules/Python OptionalModules/SvnSerialiser OptionalModules/World/NPC OptionalModules/World/TreePopulator --- .nant/bamboo.build | 1 - .nant/local.include | 10 +- .../LoadRegions/LoadRegionsPlugin.cs | 8 +- .../RemoteController/RemoteAdminPlugin.cs | 2 +- OpenSim/Data/Tests/BasicRegionTest.cs | 2 +- OpenSim/Region/Application/HGOpenSimNode.cs | 2 +- OpenSim/Region/Application/OpenSim.cs | 4 +- OpenSim/Region/Application/OpenSimBase.cs | 2 +- OpenSim/Region/ClientStack/ClientStackManager.cs | 2 +- .../Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- .../Region/ClientStack/RegionApplicationBase.cs | 2 +- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 232 +++ .../Region/CoreModules/Avatar/Chat/ChatModule.cs | 287 ++++ .../CoreModules/Avatar/Combat/CombatModule.cs | 154 ++ .../Currency/SampleMoney/SampleMoneyModule.cs | 1605 ++++++++++++++++++++ .../CoreModules/Avatar/Dialog/DialogModule.cs | 143 ++ .../CoreModules/Avatar/Friends/FriendsModule.cs | 1003 ++++++++++++ .../CoreModules/Avatar/Gestures/GesturesModule.cs | 104 ++ .../CoreModules/Avatar/Groups/GroupsModule.cs | 223 +++ .../Avatar/InstantMessage/InstantMessageModule.cs | 170 +++ .../Avatar/InstantMessage/MessageTransferModule.cs | 655 ++++++++ .../Avatar/InstantMessage/PresenceModule.cs | 426 ++++++ .../Archiver/InventoryArchiveReadRequest.cs | 279 ++++ .../Archiver/InventoryArchiveWriteRequest.cs | 247 +++ .../Inventory/Transfer/InventoryTransferModule.cs | 389 +++++ .../Region/CoreModules/Avatar/Lure/LureModule.cs | 176 +++ .../CoreModules/Avatar/ObjectCaps/ObjectAdd.cs | 368 +++++ .../Avatar/Profiles/AvatarProfilesModule.cs | 145 ++ .../Communications/Local/LocalInterregionComms.cs | 244 +++ .../Communications/REST/RESTInterregionComms.cs | 960 ++++++++++++ .../Framework/EventQueue/EventQueueGetModule.cs | 630 ++++++++ .../Framework/EventQueue/EventQueueHelper.cs | 459 ++++++ .../Framework/InterfaceCommander/Command.cs | 216 +++ .../Framework/InterfaceCommander/Commander.cs | 182 +++ .../Hypergrid/HGStandaloneAssetService.cs | 201 +++ .../Hypergrid/HGStandaloneInventoryService.cs | 314 ++++ .../CoreModules/Hypergrid/HGWorldMapModule.cs | 178 +++ .../InterGrid/OpenGridProtocolModule.cs | 1273 ++++++++++++++++ .../DynamicTexture/DynamicTextureModule.cs | 332 ++++ .../Scripting/EMailModules/EmailModule.cs | 288 ++++ .../Scripting/HttpRequest/ScriptsHttpRequests.cs | 437 ++++++ .../Scripting/LoadImageURL/LoadImageURLModule.cs | 229 +++ .../Scripting/VectorRender/VectorRenderModule.cs | 515 +++++++ .../Scripting/WorldComm/WorldCommModule.cs | 726 +++++++++ .../CoreModules/Scripting/XMLRPC/XMLRPCModule.cs | 726 +++++++++ .../CoreModules/World/Archiver/ArchiveConstants.cs | 128 ++ .../World/Archiver/ArchiveReadRequest.cs | 460 ++++++ .../World/Archiver/ArchiveWriteRequestExecution.cs | 161 ++ .../Archiver/ArchiveWriteRequestPreparation.cs | 333 ++++ .../CoreModules/World/Archiver/ArchiverModule.cs | 95 ++ .../CoreModules/World/Archiver/AssetsArchiver.cs | 143 ++ .../CoreModules/World/Archiver/AssetsDearchiver.cs | 184 +++ .../CoreModules/World/Archiver/AssetsRequest.cs | 138 ++ .../World/Archiver/RegionSettingsSerializer.cs | 258 ++++ .../CoreModules/World/Archiver/TarArchiveReader.cs | 195 +++ .../CoreModules/World/Archiver/TarArchiveWriter.cs | 202 +++ .../World/Archiver/Tests/ArchiverTests.cs | 188 +++ .../World/Estate/EstateManagementModule.cs | 1012 ++++++++++++ .../World/Estate/EstateTerrainXferHandler.cs | 127 ++ .../Region/CoreModules/World/Land/LandChannel.cs | 188 +++ .../CoreModules/World/Land/LandManagementModule.cs | 1347 ++++++++++++++++ .../Region/CoreModules/World/Land/LandObject.cs | 930 ++++++++++++ .../World/Permissions/PermissionsModule.cs | 1498 ++++++++++++++++++ .../World/Serialiser/IFileSerialiser.cs | 36 + .../World/Serialiser/SerialiseObjects.cs | 125 ++ .../World/Serialiser/SerialiseTerrain.cs | 53 + .../World/Serialiser/SerialiserModule.cs | 226 +++ .../Region/CoreModules/World/Sound/SoundModule.cs | 97 ++ OpenSim/Region/CoreModules/World/Sun/SunModule.cs | 434 ++++++ .../World/Terrain/DefaultEffects/ChannelDigger.cs | 107 ++ .../World/Terrain/Effects/CookieCutter.cs | 125 ++ .../Terrain/Effects/DefaultTerrainGenerator.cs | 56 + .../CoreModules/World/Terrain/FileLoaders/BMP.cs | 76 + .../CoreModules/World/Terrain/FileLoaders/GIF.cs | 61 + .../Terrain/FileLoaders/GenericSystemDrawing.cs | 195 +++ .../CoreModules/World/Terrain/FileLoaders/JPEG.cs | 112 ++ .../CoreModules/World/Terrain/FileLoaders/LLRAW.cs | 250 +++ .../CoreModules/World/Terrain/FileLoaders/PNG.cs | 61 + .../CoreModules/World/Terrain/FileLoaders/RAW32.cs | 170 +++ .../CoreModules/World/Terrain/FileLoaders/TIFF.cs | 61 + .../World/Terrain/FileLoaders/Terragen.cs | 142 ++ .../World/Terrain/FloodBrushes/FlattenArea.cs | 70 + .../World/Terrain/FloodBrushes/LowerArea.cs | 54 + .../World/Terrain/FloodBrushes/NoiseArea.cs | 58 + .../World/Terrain/FloodBrushes/RaiseArea.cs | 54 + .../World/Terrain/FloodBrushes/RevertArea.cs | 67 + .../World/Terrain/FloodBrushes/SmoothArea.cs | 114 ++ .../CoreModules/World/Terrain/ITerrainEffect.cs | 36 + .../World/Terrain/ITerrainFloodEffect.cs | 37 + .../CoreModules/World/Terrain/ITerrainLoader.cs | 42 + .../CoreModules/World/Terrain/ITerrainModule.cs | 61 + .../World/Terrain/ITerrainPaintableEffect.cs | 36 + .../World/Terrain/PaintBrushes/ErodeSphere.cs | 318 ++++ .../World/Terrain/PaintBrushes/FlattenSphere.cs | 101 ++ .../World/Terrain/PaintBrushes/LowerSphere.cs | 84 + .../World/Terrain/PaintBrushes/NoiseSphere.cs | 67 + .../World/Terrain/PaintBrushes/OlsenSphere.cs | 223 +++ .../World/Terrain/PaintBrushes/RaiseSphere.cs | 80 + .../World/Terrain/PaintBrushes/RevertSphere.cs | 80 + .../World/Terrain/PaintBrushes/SmoothSphere.cs | 100 ++ .../World/Terrain/PaintBrushes/WeatherSphere.cs | 211 +++ .../CoreModules/World/Terrain/TerrainException.cs | 46 + .../CoreModules/World/Terrain/TerrainModule.cs | 1001 ++++++++++++ .../CoreModules/World/Terrain/Tests/TerrainTest.cs | 118 ++ .../World/Vegetation/VegetationModule.cs | 118 ++ .../Region/CoreModules/World/Wind/WindModule.cs | 207 +++ .../World/WorldMap/IMapTileTerrainRenderer.cs | 39 + .../CoreModules/World/WorldMap/MapImageModule.cs | 586 +++++++ .../CoreModules/World/WorldMap/MapSearchModule.cs | 172 +++ .../World/WorldMap/ShadedMapTileRenderer.cs | 249 +++ .../World/WorldMap/TexturedMapTileRenderer.cs | 411 +++++ .../CoreModules/World/WorldMap/WorldMapModule.cs | 905 +++++++++++ OpenSim/Region/DataSnapshot/LandSnapshot.cs | 2 +- OpenSim/Region/DataSnapshot/ObjectSnapshot.cs | 2 +- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 232 --- .../Modules/Avatar/Chat/ChannelState.cs | 628 -------- .../Environment/Modules/Avatar/Chat/ChatModule.cs | 287 ---- .../Modules/Avatar/Chat/IRCBridgeModule.cs | 219 --- .../Modules/Avatar/Chat/IRCConnector.cs | 887 ----------- .../Environment/Modules/Avatar/Chat/RegionState.cs | 424 ------ .../Modules/Avatar/Combat/CombatModule.cs | 154 -- .../Modules/Avatar/Concierge/ConciergeModule.cs | 604 -------- .../Modules/Avatar/Concierge/ConciergeServer.py | 130 -- .../Currency/SampleMoney/SampleMoneyModule.cs | 1605 -------------------- .../Modules/Avatar/Dialog/DialogModule.cs | 143 -- .../Modules/Avatar/Friends/FriendsModule.cs | 1003 ------------ .../Modules/Avatar/Gestures/GesturesModule.cs | 104 -- .../Modules/Avatar/Groups/GroupsModule.cs | 223 --- .../Avatar/InstantMessage/InstantMessageModule.cs | 170 --- .../Avatar/InstantMessage/MessageTransferModule.cs | 655 -------- .../Avatar/InstantMessage/PresenceModule.cs | 426 ------ .../Archiver/InventoryArchiveReadRequest.cs | 279 ---- .../Archiver/InventoryArchiveWriteRequest.cs | 247 --- .../Inventory/Transfer/InventoryTransferModule.cs | 389 ----- .../Environment/Modules/Avatar/Lure/LureModule.cs | 176 --- .../Modules/Avatar/ObjectCaps/ObjectAdd.cs | 368 ----- .../Avatar/Profiles/AvatarProfilesModule.cs | 145 -- .../Voice/AsterixVoice/AsteriskVoiceModule.cs | 292 ---- .../Avatar/Voice/SIPVoice/SIPVoiceModule.cs | 202 --- .../Communications/Local/LocalInterregionComms.cs | 244 --- .../Communications/REST/RESTInterregionComms.cs | 960 ------------ .../ContentManagementSystem/AuraMetaEntity.cs | 161 -- .../ContentManagementSystem/BeamMetaEntity.cs | 139 -- .../ContentManagementSystem/CMController.cs | 757 --------- .../ContentManagementSystem/CMEntityCollection.cs | 193 --- .../Modules/ContentManagementSystem/CMModel.cs | 362 ----- .../Modules/ContentManagementSystem/CMView.cs | 206 --- .../ContentManagementEntity.cs | 383 ----- .../ContentManagementModule.cs | 163 -- .../ContentManagementSystem/FileSystemDatabase.cs | 317 ---- .../Modules/ContentManagementSystem/GitDatabase.cs | 167 -- .../ContentManagementSystem/IContentDatabase.cs | 94 -- .../Modules/ContentManagementSystem/MetaEntity.cs | 274 ---- .../ContentManagementSystem/PointMetaEntity.cs | 116 -- .../Modules/ContentManagementSystem/README | 52 - .../SceneObjectGroupDiff.cs | 218 --- .../Framework/EventQueue/EventQueueGetModule.cs | 630 -------- .../Framework/EventQueue/EventQueueHelper.cs | 459 ------ .../Framework/InterfaceCommander/Command.cs | 216 --- .../Framework/InterfaceCommander/Commander.cs | 182 --- .../Modules/Grid/Interregion/IInterregionModule.cs | 43 - .../Modules/Grid/Interregion/InterregionModule.cs | 199 --- .../Modules/Grid/Interregion/RemotingObject.cs | 77 - .../Modules/Hypergrid/HGStandaloneAssetService.cs | 201 --- .../Hypergrid/HGStandaloneInventoryService.cs | 314 ---- .../Modules/Hypergrid/HGWorldMapModule.cs | 178 --- .../Modules/InterGrid/OpenGridProtocolModule.cs | 1273 ---------------- .../DynamicTexture/DynamicTextureModule.cs | 332 ---- .../Modules/Scripting/EMailModules/EmailModule.cs | 288 ---- .../Scripting/HttpRequest/ScriptsHttpRequests.cs | 437 ------ .../Scripting/LoadImageURL/LoadImageURLModule.cs | 229 --- .../Scripting/VectorRender/VectorRenderModule.cs | 515 ------- .../Modules/Scripting/WorldComm/WorldCommModule.cs | 726 --------- .../Modules/Scripting/XMLRPC/XMLRPCModule.cs | 726 --------- .../Modules/World/Archiver/ArchiveConstants.cs | 128 -- .../Modules/World/Archiver/ArchiveReadRequest.cs | 460 ------ .../World/Archiver/ArchiveWriteRequestExecution.cs | 161 -- .../Archiver/ArchiveWriteRequestPreparation.cs | 333 ---- .../Modules/World/Archiver/ArchiverModule.cs | 95 -- .../Modules/World/Archiver/AssetsArchiver.cs | 143 -- .../Modules/World/Archiver/AssetsDearchiver.cs | 184 --- .../Modules/World/Archiver/AssetsRequest.cs | 138 -- .../World/Archiver/RegionSettingsSerializer.cs | 258 ---- .../Modules/World/Archiver/TarArchiveReader.cs | 195 --- .../Modules/World/Archiver/TarArchiveWriter.cs | 202 --- .../Modules/World/Archiver/Tests/ArchiverTests.cs | 188 --- .../Modules/World/Estate/EstateManagementModule.cs | 1012 ------------ .../World/Estate/EstateTerrainXferHandler.cs | 127 -- .../Environment/Modules/World/Land/LandChannel.cs | 188 --- .../Modules/World/Land/LandManagementModule.cs | 1347 ---------------- .../Environment/Modules/World/Land/LandObject.cs | 930 ------------ .../Environment/Modules/World/NPC/NPCAvatar.cs | 1060 ------------- .../Environment/Modules/World/NPC/NPCModule.cs | 68 - .../Modules/World/Permissions/PermissionsModule.cs | 1498 ------------------ .../Modules/World/Serialiser/IFileSerialiser.cs | 36 - .../Modules/World/Serialiser/SerialiseObjects.cs | 125 -- .../Modules/World/Serialiser/SerialiseTerrain.cs | 53 - .../Modules/World/Serialiser/SerialiserModule.cs | 226 --- .../Environment/Modules/World/Sound/SoundModule.cs | 97 -- .../Environment/Modules/World/Sun/SunModule.cs | 434 ------ .../Modules/World/Terrain/Effects/CookieCutter.cs | 125 -- .../Terrain/Effects/DefaultTerrainGenerator.cs | 56 - .../Modules/World/Terrain/FileLoaders/BMP.cs | 76 - .../Modules/World/Terrain/FileLoaders/GIF.cs | 61 - .../Terrain/FileLoaders/GenericSystemDrawing.cs | 195 --- .../Modules/World/Terrain/FileLoaders/JPEG.cs | 112 -- .../Modules/World/Terrain/FileLoaders/LLRAW.cs | 250 --- .../Modules/World/Terrain/FileLoaders/PNG.cs | 61 - .../Modules/World/Terrain/FileLoaders/RAW32.cs | 170 --- .../Modules/World/Terrain/FileLoaders/TIFF.cs | 61 - .../Modules/World/Terrain/FileLoaders/Terragen.cs | 142 -- .../World/Terrain/FloodBrushes/FlattenArea.cs | 70 - .../World/Terrain/FloodBrushes/LowerArea.cs | 54 - .../World/Terrain/FloodBrushes/NoiseArea.cs | 58 - .../World/Terrain/FloodBrushes/RaiseArea.cs | 54 - .../World/Terrain/FloodBrushes/RevertArea.cs | 67 - .../World/Terrain/FloodBrushes/SmoothArea.cs | 114 -- .../Modules/World/Terrain/ITerrainEffect.cs | 36 - .../Modules/World/Terrain/ITerrainFloodEffect.cs | 37 - .../Modules/World/Terrain/ITerrainLoader.cs | 42 - .../Modules/World/Terrain/ITerrainModule.cs | 61 - .../World/Terrain/ITerrainPaintableEffect.cs | 36 - .../World/Terrain/PaintBrushes/ErodeSphere.cs | 318 ---- .../World/Terrain/PaintBrushes/FlattenSphere.cs | 101 -- .../World/Terrain/PaintBrushes/LowerSphere.cs | 84 - .../World/Terrain/PaintBrushes/NoiseSphere.cs | 67 - .../World/Terrain/PaintBrushes/OlsenSphere.cs | 223 --- .../World/Terrain/PaintBrushes/RaiseSphere.cs | 80 - .../World/Terrain/PaintBrushes/RevertSphere.cs | 80 - .../World/Terrain/PaintBrushes/SmoothSphere.cs | 100 -- .../World/Terrain/PaintBrushes/WeatherSphere.cs | 211 --- .../Modules/World/Terrain/TerrainException.cs | 46 - .../Modules/World/Terrain/TerrainModule.cs | 1001 ------------ .../Modules/World/Terrain/Tests/TerrainTest.cs | 118 -- .../World/TreePopulator/TreePopulatorModule.cs | 304 ---- .../Modules/World/Vegetation/VegetationModule.cs | 118 -- .../Environment/Modules/World/Wind/WindModule.cs | 207 --- .../World/WorldMap/IMapTileTerrainRenderer.cs | 39 - .../Modules/World/WorldMap/MapImageModule.cs | 586 ------- .../Modules/World/WorldMap/MapSearchModule.cs | 172 --- .../World/WorldMap/ShadedMapTileRenderer.cs | 249 --- .../World/WorldMap/TexturedMapTileRenderer.cs | 411 ----- .../Modules/World/WorldMap/WorldMapModule.cs | 905 ----------- OpenSim/Region/Framework/Interfaces/IWorldComm.cs | 1 - OpenSim/Region/Framework/Interfaces/IXMLRPC.cs | 2 - .../Framework/Scenes/Hypergrid/HGAssetMapper.cs | 1 - .../Scenes/Hypergrid/HGScene.Inventory.cs | 1 - .../Region/Framework/Scenes/Hypergrid/HGScene.cs | 1 - .../Hypergrid/HGSceneCommunicationService.cs | 1 - .../Scenes/Tests/SceneObjectBasicTests.cs | 2 +- .../Scenes/Tests/SceneObjectLinkingTests.cs | 2 +- .../Framework/Scenes/Tests/ScenePresenceTests.cs | 4 +- .../Scenes/Tests/StandaloneTeleportTests.cs | 2 +- .../Modules/Python/Properties/AssemblyInfo.cs | 63 - OpenSim/Region/Modules/Python/PythonAPI/Console.cs | 48 - OpenSim/Region/Modules/Python/PythonModule.cs | 71 - .../SvnSerialiser/Properties/AssemblyInfo.cs | 62 - .../Modules/SvnSerialiser/SvnBackupModule.cs | 396 ----- .../DefaultEffects/Effects/ChannelDigger.cs | 107 -- .../OptionalModules/Avatar/Chat/ChannelState.cs | 628 ++++++++ .../OptionalModules/Avatar/Chat/IRCBridgeModule.cs | 219 +++ .../OptionalModules/Avatar/Chat/IRCConnector.cs | 887 +++++++++++ .../OptionalModules/Avatar/Chat/RegionState.cs | 424 ++++++ .../Avatar/Concierge/ConciergeModule.cs | 604 ++++++++ .../Avatar/Concierge/ConciergeServer.py | 130 ++ .../Voice/AsterixVoice/AsteriskVoiceModule.cs | 292 ++++ .../Avatar/Voice/SIPVoice/SIPVoiceModule.cs | 202 +++ .../ContentManagementSystem/AuraMetaEntity.cs | 161 ++ .../ContentManagementSystem/BeamMetaEntity.cs | 139 ++ .../ContentManagementSystem/CMController.cs | 757 +++++++++ .../ContentManagementSystem/CMEntityCollection.cs | 193 +++ .../ContentManagementSystem/CMModel.cs | 362 +++++ .../ContentManagementSystem/CMView.cs | 206 +++ .../ContentManagementEntity.cs | 383 +++++ .../ContentManagementModule.cs | 163 ++ .../ContentManagementSystem/FileSystemDatabase.cs | 317 ++++ .../ContentManagementSystem/GitDatabase.cs | 167 ++ .../ContentManagementSystem/IContentDatabase.cs | 94 ++ .../ContentManagementSystem/MetaEntity.cs | 274 ++++ .../ContentManagementSystem/PointMetaEntity.cs | 116 ++ .../OptionalModules/ContentManagementSystem/README | 52 + .../SceneObjectGroupDiff.cs | 218 +++ .../Grid/Interregion/IInterregionModule.cs | 43 + .../Grid/Interregion/InterregionModule.cs | 199 +++ .../Grid/Interregion/RemotingObject.cs | 77 + .../OptionalModules/Python/PythonAPI/Console.cs | 48 + .../Region/OptionalModules/Python/PythonModule.cs | 71 + OpenSim/Region/OptionalModules/README | 9 + .../SvnSerialiser/Properties/AssemblyInfo.cs | 62 + .../SvnSerialiser/SvnBackupModule.cs | 396 +++++ .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 1060 +++++++++++++ .../Region/OptionalModules/World/NPC/NPCModule.cs | 68 + .../World/TreePopulator/TreePopulatorModule.cs | 304 ++++ .../ScriptEngine/DotNetEngine/EventManager.cs | 4 +- .../ScriptEngine/DotNetEngine/ScriptEngine.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 10 +- .../Api/Implementation/Plugins/HttpRequest.cs | 2 +- .../Shared/Api/Implementation/Plugins/Listener.cs | 2 +- .../Api/Implementation/Plugins/XmlRequest.cs | 2 +- ...nSim.Region.ScriptEngine.Shared.Api.Runtime.mdp | 2 +- OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 2 +- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 2 +- .../Shared/Instance/ScriptSerializer.cs | 2 +- .../Region/ScriptEngine/XEngine/EventManager.cs | 2 +- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 2 +- TESTING.txt | 2 +- prebuild.xml | 214 ++- 307 files changed, 39706 insertions(+), 39776 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs create mode 100644 OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs create mode 100644 OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs create mode 100644 OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs create mode 100644 OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs create mode 100644 OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs create mode 100644 OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs create mode 100644 OpenSim/Region/CoreModules/Hypergrid/HGStandaloneAssetService.cs create mode 100644 OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryService.cs create mode 100644 OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs create mode 100644 OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs create mode 100644 OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs create mode 100644 OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs create mode 100644 OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs create mode 100644 OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs create mode 100644 OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs create mode 100644 OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs create mode 100644 OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveConstants.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/RegionSettingsSerializer.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs create mode 100644 OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs create mode 100644 OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs create mode 100644 OpenSim/Region/CoreModules/World/Land/LandChannel.cs create mode 100644 OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Land/LandObject.cs create mode 100644 OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Serialiser/IFileSerialiser.cs create mode 100644 OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs create mode 100644 OpenSim/Region/CoreModules/World/Serialiser/SerialiseTerrain.cs create mode 100644 OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Sound/SoundModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Sun/SunModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/DefaultEffects/ChannelDigger.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/ITerrainEffect.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/ITerrainModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/TerrainException.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs create mode 100644 OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Wind/WindModule.cs create mode 100644 OpenSim/Region/CoreModules/World/WorldMap/IMapTileTerrainRenderer.cs create mode 100644 OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs create mode 100644 OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs create mode 100644 OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs create mode 100644 OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs create mode 100644 OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs delete mode 100755 OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs delete mode 100644 OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/README delete mode 100644 OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs delete mode 100644 OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs delete mode 100644 OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs delete mode 100644 OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs delete mode 100644 OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs delete mode 100644 OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs delete mode 100644 OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs delete mode 100644 OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs delete mode 100644 OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Land/LandObject.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs delete mode 100644 OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs delete mode 100644 OpenSim/Region/Modules/Python/Properties/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Modules/Python/PythonAPI/Console.cs delete mode 100644 OpenSim/Region/Modules/Python/PythonModule.cs delete mode 100644 OpenSim/Region/Modules/SvnSerialiser/Properties/AssemblyInfo.cs delete mode 100644 OpenSim/Region/Modules/SvnSerialiser/SvnBackupModule.cs delete mode 100644 OpenSim/Region/Modules/Terrain/Extensions/DefaultEffects/Effects/ChannelDigger.cs create mode 100644 OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs create mode 100644 OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs create mode 100644 OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs create mode 100644 OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs create mode 100644 OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs create mode 100755 OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeServer.py create mode 100644 OpenSim/Region/OptionalModules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs create mode 100644 OpenSim/Region/OptionalModules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/README create mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs create mode 100644 OpenSim/Region/OptionalModules/Grid/Interregion/IInterregionModule.cs create mode 100644 OpenSim/Region/OptionalModules/Grid/Interregion/InterregionModule.cs create mode 100644 OpenSim/Region/OptionalModules/Grid/Interregion/RemotingObject.cs create mode 100644 OpenSim/Region/OptionalModules/Python/PythonAPI/Console.cs create mode 100644 OpenSim/Region/OptionalModules/Python/PythonModule.cs create mode 100644 OpenSim/Region/OptionalModules/README create mode 100644 OpenSim/Region/OptionalModules/SvnSerialiser/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs create mode 100644 OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs create mode 100644 OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs create mode 100644 OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs diff --git a/.nant/bamboo.build b/.nant/bamboo.build index c8756f8..fa0541a 100644 --- a/.nant/bamboo.build +++ b/.nant/bamboo.build @@ -43,7 +43,6 @@ - diff --git a/.nant/local.include b/.nant/local.include index d2a8c7c..8652376 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -40,7 +40,6 @@ - @@ -110,13 +109,13 @@ - + - + - + - + @@ -170,7 +169,6 @@ - diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs index b9a0a64..bd98045 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -34,10 +34,10 @@ using OpenSim.Framework; using OpenSim.Framework.RegionLoader.Filesystem; using OpenSim.Framework.RegionLoader.Web; -using OpenSim.Region.Environment.Modules.Scripting.DynamicTexture; -using OpenSim.Region.Environment.Modules.Avatar.InstantMessage; -using OpenSim.Region.Environment.Modules.Scripting.LoadImageURL; -using OpenSim.Region.Environment.Modules.Scripting.XMLRPC; +using OpenSim.Region.CoreModules.Scripting.DynamicTexture; +using OpenSim.Region.CoreModules.Avatar.InstantMessage; +using OpenSim.Region.CoreModules.Scripting.LoadImageURL; +using OpenSim.Region.CoreModules.Scripting.XMLRPC; using OpenSim.Region.CoreModules.Agent.AssetTransaction; namespace OpenSim.ApplicationPlugins.LoadRegions diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index a036371..43ae818 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -39,7 +39,7 @@ using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Terrain; +using OpenSim.Region.CoreModules.World.Terrain; using System.Collections.Generic; namespace OpenSim.ApplicationPlugins.RemoteController diff --git a/OpenSim/Data/Tests/BasicRegionTest.cs b/OpenSim/Data/Tests/BasicRegionTest.cs index 70d8f8a..d60dadd 100644 --- a/OpenSim/Data/Tests/BasicRegionTest.cs +++ b/OpenSim/Data/Tests/BasicRegionTest.cs @@ -35,7 +35,7 @@ using OpenSim.Framework; using OpenSim.Data; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Land; +using OpenSim.Region.CoreModules.World.Land; using OpenMetaverse; namespace OpenSim.Data.Tests diff --git a/OpenSim/Region/Application/HGOpenSimNode.cs b/OpenSim/Region/Application/HGOpenSimNode.cs index c0f57f1..458c6af 100644 --- a/OpenSim/Region/Application/HGOpenSimNode.cs +++ b/OpenSim/Region/Application/HGOpenSimNode.cs @@ -43,7 +43,7 @@ using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Region.Communications.Local; using OpenSim.Region.Communications.Hypergrid; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 1c7751d..db6c0f1 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -41,8 +41,8 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Statistics; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.Avatar.Inventory.Archiver; -using Timer=System.Timers.Timer; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; +using Timer = System.Timers.Timer; namespace OpenSim { diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f2ea81d..aab80d9 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -44,7 +44,7 @@ using OpenSim.Framework.Statistics; using OpenSim.Region.ClientStack; using OpenSim.Region.Communications.Local; using OpenSim.Region.Communications.OGS1; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/ClientStack/ClientStackManager.cs b/OpenSim/Region/ClientStack/ClientStackManager.cs index 6cad7c9..f947d06 100644 --- a/OpenSim/Region/ClientStack/ClientStackManager.cs +++ b/OpenSim/Region/ClientStack/ClientStackManager.cs @@ -35,7 +35,7 @@ using OpenSim.Region.ClientStack; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; -namespace OpenSim.Region.Environment +namespace OpenSim.Region.ClientStack { public class ClientStackManager { diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index f53174a..a1263a1 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -798,7 +798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Starts up the timers to check the client and resend unacked packets - /// Adds the client to the OpenSim.Region.Environment.Scenes.Scene + /// Adds the client to the OpenSim.Region.Framework.Scenes.Scene /// protected virtual void InitNewClient() { diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index 18d8c5c..24ebd7e 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -38,7 +38,7 @@ using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Servers; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules; using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.ClientStack diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs new file mode 100644 index 0000000..d084dbd --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -0,0 +1,232 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; + +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory +{ + public class AvatarFactoryModule : IAvatarFactory, IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene = null; + private static readonly AvatarAppearance def = new AvatarAppearance(); + + public bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance appearance) + { + CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(avatarId); + //if ((profile != null) && (profile.RootFolder != null)) + if (profile != null) + { + appearance = m_scene.CommsManager.AvatarService.GetUserAppearance(avatarId); + if (appearance != null) + { + //SetAppearanceAssets(profile, ref appearance); + //m_log.DebugFormat("[APPEARANCE]: Found : {0}", appearance.ToString()); + return true; + } + } + + appearance = CreateDefault(avatarId); + m_log.ErrorFormat("[APPEARANCE]: Appearance not found for {0}, creating default", avatarId); + return false; + } + + private AvatarAppearance CreateDefault(UUID avatarId) + { + AvatarAppearance appearance = null; + AvatarWearable[] wearables; + byte[] visualParams; + GetDefaultAvatarAppearance(out wearables, out visualParams); + appearance = new AvatarAppearance(avatarId, wearables, visualParams); + + return appearance; + } + + public void Initialise(Scene scene, IConfigSource source) + { + scene.RegisterModuleInterface(this); + scene.EventManager.OnNewClient += NewClient; + + if (m_scene == null) + { + m_scene = scene; + } + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "Default Avatar Factory"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnAvatarNowWearing += AvatarIsWearing; + } + + public void RemoveClient(IClientAPI client) + { + // client.OnAvatarNowWearing -= AvatarIsWearing; + } + + + public void SetAppearanceAssets(CachedUserInfo profile, ref AvatarAppearance appearance) + { + if (profile.RootFolder != null) + { + for (int i = 0; i < 13; i++) + { + if (appearance.Wearables[i].ItemID == UUID.Zero) + { + appearance.Wearables[i].AssetID = UUID.Zero; + } + else + { + InventoryItemBase baseItem = profile.RootFolder.FindItem(appearance.Wearables[i].ItemID); + + if (baseItem != null) + { + appearance.Wearables[i].AssetID = baseItem.AssetID; + } + else + { + m_log.ErrorFormat("[APPEARANCE]: Can't find inventory item {0}, setting to default", appearance.Wearables[i].ItemID); + appearance.Wearables[i].AssetID = def.Wearables[i].AssetID; + } + } + } + } + else + { + m_log.Error("[APPEARANCE]: you have no inventory, appearance stuff isn't going to work"); + } + } + + /// + /// Update what the avatar is wearing using an item from their inventory. + /// + /// + /// + public void AvatarIsWearing(Object sender, AvatarWearingArgs e) + { + IClientAPI clientView = (IClientAPI)sender; + ScenePresence avatar = m_scene.GetScenePresence(clientView.AgentId); + + if (avatar == null) + { + m_log.Error("[APPEARANCE]: Avatar is child agent, ignoring AvatarIsWearing event"); + return; + } + + CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId); + + AvatarAppearance avatAppearance = null; + if (!TryGetAvatarAppearance(clientView.AgentId, out avatAppearance)) + { + m_log.Warn("[APPEARANCE]: We didn't seem to find the appearance, falling back to ScenePresence"); + avatAppearance = avatar.Appearance; + } + + //m_log.DebugFormat("[APPEARANCE]: Received wearables for {0}", clientView.Name); + + if (profile != null) + { + if (profile.RootFolder != null) + { + foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) + { + if (wear.Type < 13) + { + avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; + } + } + + SetAppearanceAssets(profile, ref avatAppearance); + + m_scene.CommsManager.AvatarService.UpdateUserAppearance(clientView.AgentId, avatAppearance); + avatar.Appearance = avatAppearance; + } + else + { + m_log.WarnFormat( + "[APPEARANCE]: Inventory has not yet been received for {0}, cannot set wearables", + clientView.Name); + } + } + else + { + m_log.WarnFormat("[APPEARANCE]: Cannot set wearables for {0}, no user profile found", clientView.Name); + } + } + + public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) + { + visualParams = GetDefaultVisualParams(); + wearables = AvatarWearable.DefaultWearables; + } + + public void UpdateDatabase(UUID user, AvatarAppearance appearance) + { + m_scene.CommsManager.AvatarService.UpdateUserAppearance(user, appearance); + } + + private static byte[] GetDefaultVisualParams() + { + byte[] visualParams; + visualParams = new byte[218]; + for (int i = 0; i < 218; i++) + { + visualParams[i] = 100; + } + return visualParams; + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs new file mode 100644 index 0000000..f036faf --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -0,0 +1,287 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Sockets; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Chat +{ + public class ChatModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const int DEBUG_CHANNEL = 2147483647; + + private bool m_enabled = true; + private int m_saydistance = 30; + private int m_shoutdistance = 100; + private int m_whisperdistance = 10; + private List m_scenes = new List(); + + internal object m_syncInit = new object(); + + #region IRegionModule Members + public virtual void Initialise(Scene scene, IConfigSource config) + { + // wrap this in a try block so that defaults will work if + // the config file doesn't specify otherwise. + try + { + m_enabled = config.Configs["Chat"].GetBoolean("enabled", m_enabled); + if (!m_enabled) return; + + m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); + m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); + m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); + } + catch (Exception) + { + } + + lock (m_syncInit) + { + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnChatFromWorld += OnChatFromWorld; + scene.EventManager.OnChatBroadcast += OnChatBroadcast; + } + } + + m_log.InfoFormat("[CHAT] initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, + m_whisperdistance, m_saydistance, m_shoutdistance); + } + public virtual void PostInitialise() + { + } + + public virtual void Close() + { + } + + public virtual string Name + { + get { return "ChatModule"; } + } + + public virtual bool IsSharedModule + { + get { return true; } + } + + #endregion + + + public virtual void OnNewClient(IClientAPI client) + { + client.OnChatFromClient += OnChatFromClient; + } + + protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c) + { + ScenePresence avatar; + Scene scene = (Scene)c.Scene; + if ((avatar = scene.GetScenePresence(c.Sender.AgentId)) != null) + c.Position = avatar.AbsolutePosition; + + return c; + } + + public virtual void OnChatFromClient(Object sender, OSChatMessage c) + { + c = FixPositionOfChatMessage(c); + + // redistribute to interested subscribers + Scene scene = (Scene)c.Scene; + scene.EventManager.TriggerOnChatFromClient(sender, c); + + // early return if not on public or debug channel + if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; + + // sanity check: + if (c.Sender == null) + { + m_log.ErrorFormat("[CHAT] OnChatFromClient from {0} has empty Sender field!", sender); + return; + } + + DeliverChatToAvatars(ChatSourceType.Agent, c); + } + + public virtual void OnChatFromWorld(Object sender, OSChatMessage c) + { + // early return if not on public or debug channel + if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; + + DeliverChatToAvatars(ChatSourceType.Object, c); + } + + protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) + { + string fromName = c.From; + UUID fromID = UUID.Zero; + string message = c.Message; + IScene scene = c.Scene; + Vector3 fromPos = c.Position; + Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, + scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + + if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; + + switch (sourceType) + { + case ChatSourceType.Agent: + if (!(scene is Scene)) + { + m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}", + scene.RegionInfo.RegionName, c.Sender.AgentId); + return; + } + ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId); + fromPos = avatar.AbsolutePosition; + fromName = avatar.Name; + fromID = c.Sender.AgentId; + + break; + + case ChatSourceType.Object: + fromID = c.SenderUUID; + + break; + } + + // TODO: iterate over message + if (message.Length >= 1000) // libomv limit + message = message.Substring(0, 1000); + + // m_log.DebugFormat("[CHAT]: DCTA: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, c.Type, sourceType); + + foreach (Scene s in m_scenes) + { + s.ForEachScenePresence(delegate(ScenePresence presence) + { + TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, + c.Type, message, sourceType); + }); + } + } + + + static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); + public virtual void OnChatBroadcast(Object sender, OSChatMessage c) + { + // unless the chat to be broadcast is of type Region, we + // drop it if its channel is neither 0 nor DEBUG_CHANNEL + if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL && c.Type != ChatTypeEnum.Region) return; + + ChatTypeEnum cType = c.Type; + if (c.Channel == DEBUG_CHANNEL) + cType = ChatTypeEnum.DebugChannel; + + if (cType == ChatTypeEnum.Region) + cType = ChatTypeEnum.Say; + + if (c.Message.Length > 1100) + c.Message = c.Message.Substring(0, 1000); + + // broadcast chat works by redistributing every incoming chat + // message to each avatar in the scene. + string fromName = c.From; + + UUID fromID = UUID.Zero; + ChatSourceType sourceType = ChatSourceType.Object; + if (null != c.Sender) + { + ScenePresence avatar = (c.Scene as Scene).GetScenePresence(c.Sender.AgentId); + fromID = c.Sender.AgentId; + fromName = avatar.Name; + sourceType = ChatSourceType.Agent; + } + + // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); + + ((Scene)c.Scene).ForEachScenePresence( + delegate(ScenePresence presence) + { + // ignore chat from child agents + if (presence.IsChildAgent) return; + + IClientAPI client = presence.ControllingClient; + + // don't forward SayOwner chat from objects to + // non-owner agents + if ((c.Type == ChatTypeEnum.Owner) && + (null != c.SenderObject) && + (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) + return; + + client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, + (byte)sourceType, (byte)ChatAudibleLevel.Fully); + }); + } + + + protected virtual void TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, + UUID fromAgentID, string fromName, ChatTypeEnum type, + string message, ChatSourceType src) + { + // don't send stuff to child agents + if (presence.IsChildAgent) return; + + Vector3 fromRegionPos = fromPos + regionPos; + Vector3 toRegionPos = presence.AbsolutePosition + + new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, + presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + + int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos)); + + if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || + type == ChatTypeEnum.Say && dis > m_saydistance || + type == ChatTypeEnum.Shout && dis > m_shoutdistance) + { + return; + } + + // TODO: should change so the message is sent through the avatar rather than direct to the ClientView + presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, + fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs new file mode 100644 index 0000000..1ed608a --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs @@ -0,0 +1,154 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Xml; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule +{ + public class CombatModule : IRegionModule + { + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Region UUIDS indexed by AgentID + /// + //private Dictionary m_rootAgents = new Dictionary(); + + /// + /// Scenes by Region Handle + /// + private Dictionary m_scenel = new Dictionary(); + + /// + /// Startup + /// + /// + /// + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_scenel) + { + if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle)) + { + m_scenel[scene.RegionInfo.RegionHandle] = scene; + } + else + { + m_scenel.Add(scene.RegionInfo.RegionHandle, scene); + } + } + + scene.EventManager.OnAvatarKilled += KillAvatar; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "CombatModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + private void KillAvatar(uint killerObjectLocalID, ScenePresence DeadAvatar) + { + if (killerObjectLocalID == 0) + DeadAvatar.ControllingClient.SendAgentAlertMessage("You committed suicide!", true); + else + { + bool foundResult = false; + string resultstring = ""; + List allav = DeadAvatar.Scene.GetScenePresences(); + try + { + foreach (ScenePresence av in allav) + { + if (av.LocalId == killerObjectLocalID) + { + av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname); + resultstring = av.Firstname + " " + av.Lastname; + foundResult = true; + } + } + } catch (System.InvalidOperationException) + { + + } + + if (!foundResult) + { + SceneObjectPart part = DeadAvatar.Scene.GetSceneObjectPart(killerObjectLocalID); + if (part != null) + { + ScenePresence av = DeadAvatar.Scene.GetScenePresence(part.OwnerID); + if (av != null) + { + av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname); + resultstring = av.Firstname + " " + av.Lastname; + DeadAvatar.ControllingClient.SendAgentAlertMessage("You got killed by " + resultstring + "!", true); + } + else + { + string killer = DeadAvatar.Scene.CommsManager.UUIDNameRequestString(part.OwnerID); + DeadAvatar.ControllingClient.SendAgentAlertMessage("You impaled yourself on " + part.Name + " owned by " + killer +"!", true); + } + //DeadAvatar.Scene. part.ObjectOwner + } + else + { + DeadAvatar.ControllingClient.SendAgentAlertMessage("You died!", true); + } + } + } + DeadAvatar.Health = 100; + DeadAvatar.Scene.TeleportClientHome(DeadAvatar.UUID, DeadAvatar.ControllingClient); + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs b/OpenSim/Region/CoreModules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs new file mode 100644 index 0000000..0a1de44 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs @@ -0,0 +1,1605 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Xml; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Currency.SampleMoney +{ + /// + /// Demo Economy/Money Module. This is not a production quality money/economy module! + /// This is a demo for you to use when making one that works for you. + /// // To use the following you need to add: + /// -helperuri
+ /// to the command line parameters you use to start up your client + /// This commonly looks like -helperuri http://127.0.0.1:9000/ + /// + /// Centralized grid structure example using OpenSimWi Redux revision 9+ + /// svn co https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux + ///
+ public class SampleMoneyModule : IMoneyModule, IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Where Stipends come from and Fees go to. + /// + // private UUID EconomyBaseAccount = UUID.Zero; + + private float EnergyEfficiency = 0f; + private bool gridmode = false; + // private ObjectPaid handerOnObjectPaid; + private bool m_enabled = true; + + private IConfigSource m_gConfig; + + private bool m_keepMoneyAcrossLogins = true; + private Dictionary m_KnownClientFunds = new Dictionary(); + // private string m_LandAddress = String.Empty; + + private int m_minFundsBeforeRefresh = 100; + private string m_MoneyAddress = String.Empty; + + /// + /// Region UUIDS indexed by AgentID + /// + private Dictionary m_rootAgents = new Dictionary(); + + /// + /// Scenes by Region Handle + /// + private Dictionary m_scenel = new Dictionary(); + + private int m_stipend = 1000; + + private int ObjectCapacity = 45000; + private int ObjectCount = 0; + private int PriceEnergyUnit = 0; + private int PriceGroupCreate = 0; + private int PriceObjectClaim = 0; + private float PriceObjectRent = 0f; + private float PriceObjectScaleFactor = 0f; + private int PriceParcelClaim = 0; + private float PriceParcelClaimFactor = 0f; + private int PriceParcelRent = 0; + private int PricePublicObjectDecay = 0; + private int PricePublicObjectDelete = 0; + private int PriceRentLight = 0; + private int PriceUpload = 0; + private int TeleportMinPrice = 0; + + private float TeleportPriceExponent = 0f; + // private int UserLevelPaysFees = 2; + // private Scene XMLRPCHandler; + + #region IMoneyModule Members + + public event ObjectPaid OnObjectPaid; + + /// + /// Startup + /// + /// + /// + public void Initialise(Scene scene, IConfigSource config) + { + m_gConfig = config; + + IConfig startupConfig = m_gConfig.Configs["Startup"]; + IConfig economyConfig = m_gConfig.Configs["Economy"]; + + + ReadConfigAndPopulate(scene, startupConfig, "Startup"); + ReadConfigAndPopulate(scene, economyConfig, "Economy"); + + if (m_enabled) + { + scene.RegisterModuleInterface(this); + BaseHttpServer httpServer = scene.CommsManager.HttpServer; + + lock (m_scenel) + { + if (m_scenel.Count == 0) + { + // XMLRPCHandler = scene; + + // To use the following you need to add: + // -helperuri
+ // to the command line parameters you use to start up your client + // This commonly looks like -helperuri http://127.0.0.1:9000/ + + if (m_MoneyAddress.Length > 0) + { + // Centralized grid structure using OpenSimWi Redux revision 9+ + // https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux + httpServer.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate); + httpServer.AddXmlRPCHandler("userAlert", UserAlert); + } + else + { + // Local Server.. enables functionality only. + httpServer.AddXmlRPCHandler("getCurrencyQuote", quote_func); + httpServer.AddXmlRPCHandler("buyCurrency", buy_func); + httpServer.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func); + httpServer.AddXmlRPCHandler("buyLandPrep", landBuy_func); + } + } + + if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle)) + { + m_scenel[scene.RegionInfo.RegionHandle] = scene; + } + else + { + m_scenel.Add(scene.RegionInfo.RegionHandle, scene); + } + } + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnMoneyTransfer += MoneyTransferAction; + scene.EventManager.OnClientClosed += ClientClosed; + scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; + scene.EventManager.OnClientClosed += ClientLoggedOut; + scene.EventManager.OnValidateLandBuy += ValidateLandBuy; + scene.EventManager.OnLandBuy += processLandBuy; + } + } + + // Please do not refactor these to be just one method + // Existing implementations need the distinction + // + public void ApplyUploadCharge(UUID agentID) + { + } + + public void ApplyGroupCreationCharge(UUID agentID) + { + } + + public void ApplyCharge(UUID agentID, int amount, string text) + { + } + + public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount) + { + string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID)); + + bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description); + + if (m_MoneyAddress.Length == 0) + BalanceUpdate(fromID, toID, give_result, description); + + return give_result; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "BetaGridLikeMoneyModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + /// + /// Parse Configuration + /// + /// + /// + /// + private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string config) + { + if (config == "Startup" && startupConfig != null) + { + gridmode = startupConfig.GetBoolean("gridmode", false); + m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule"); + } + + if (config == "Economy" && startupConfig != null) + { + ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000); + PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100); + PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10); + PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4); + PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4); + PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1); + PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f); + PriceUpload = startupConfig.GetInt("PriceUpload", 0); + PriceRentLight = startupConfig.GetInt("PriceRentLight", 5); + TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2); + TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f); + EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1); + PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1); + PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10); + PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1); + PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1); + // string EBA = startupConfig.GetString("EconomyBaseAccount", UUID.Zero.ToString()); + // Helpers.TryParse(EBA, out EconomyBaseAccount); + + // UserLevelPaysFees = startupConfig.GetInt("UserLevelPaysFees", -1); + m_stipend = startupConfig.GetInt("UserStipend", 500); + m_minFundsBeforeRefresh = startupConfig.GetInt("IssueStipendWhenClientIsBelowAmount", 10); + m_keepMoneyAcrossLogins = startupConfig.GetBoolean("KeepMoneyAcrossLogins", true); + m_MoneyAddress = startupConfig.GetString("CurrencyServer", String.Empty); + // m_LandAddress = startupConfig.GetString("LandServer", String.Empty); + } + + // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. + scene.SetObjectCapacity(ObjectCapacity); + } + + public EconomyData GetEconomyData() + { + EconomyData edata = new EconomyData(); + edata.ObjectCapacity = ObjectCapacity; + edata.ObjectCount = ObjectCount; + edata.PriceEnergyUnit = PriceEnergyUnit; + edata.PriceGroupCreate = PriceGroupCreate; + edata.PriceObjectClaim = PriceObjectClaim; + edata.PriceObjectRent = PriceObjectRent; + edata.PriceObjectScaleFactor = PriceObjectScaleFactor; + edata.PriceParcelClaim = PriceParcelClaim; + edata.PriceParcelClaimFactor = PriceParcelClaimFactor; + edata.PriceParcelRent = PriceParcelRent; + edata.PricePublicObjectDecay = PricePublicObjectDecay; + edata.PricePublicObjectDelete = PricePublicObjectDelete; + edata.PriceRentLight = PriceRentLight; + edata.PriceUpload = PriceUpload; + edata.TeleportMinPrice = TeleportMinPrice; + return edata; + } + + private void GetClientFunds(IClientAPI client) + { + // Here we check if we're in grid mode + // I imagine that the 'check balance' + // function for the client should be here or shortly after + + if (gridmode) + { + if (m_MoneyAddress.Length == 0) + { + CheckExistAndRefreshFunds(client.AgentId); + } + else + { + bool childYN = true; + ScenePresence agent = null; + //client.SecureSessionId; + Scene s = LocateSceneClientIn(client.AgentId); + if (s != null) + { + agent = s.GetScenePresence(client.AgentId); + if (agent != null) + childYN = agent.IsChildAgent; + } + if (s != null && agent != null && childYN == false) + { + //s.RegionInfo.RegionHandle; + UUID agentID = UUID.Zero; + int funds = 0; + + Hashtable hbinfo = + GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID, + s.RegionInfo.regionSecret); + if ((bool) hbinfo["success"] == true) + { + UUID.TryParse((string)hbinfo["agentId"], out agentID); + try + { + funds = (Int32) hbinfo["funds"]; + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentID); + client.SendAlertMessage("Unable to get your money balance, money operations will be unavailable"); + } + catch (InvalidCastException) + { + funds = 0; + } + + m_KnownClientFunds[agentID] = funds; + } + else + { + m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentID, + (string) hbinfo["errorMessage"]); + client.SendAlertMessage((string) hbinfo["errorMessage"]); + } + SendMoneyBalance(client, agentID, client.SessionId, UUID.Zero); + } + } + } + else + { + CheckExistAndRefreshFunds(client.AgentId); + } + + } + + /// + /// New Client Event Handler + /// + /// + private void OnNewClient(IClientAPI client) + { + GetClientFunds(client); + + // Subscribe to Money messages + client.OnEconomyDataRequest += EconomyDataRequestHandler; + client.OnMoneyBalanceRequest += SendMoneyBalance; + client.OnRequestPayPrice += requestPayPrice; + client.OnObjectBuy += ObjectBuy; + client.OnLogout += ClientClosed; + } + + /// + /// Transfer money + /// + /// + /// + /// + /// + private bool doMoneyTransfer(UUID Sender, UUID Receiver, int amount, int transactiontype, string description) + { + bool result = false; + if (amount >= 0) + { + lock (m_KnownClientFunds) + { + // If we don't know about the sender, then the sender can't + // actually be here and therefore this is likely fraud or outdated. + if (m_MoneyAddress.Length == 0) + { + if (m_KnownClientFunds.ContainsKey(Sender)) + { + // Does the sender have enough funds to give? + if (m_KnownClientFunds[Sender] >= amount) + { + // Subtract the funds from the senders account + m_KnownClientFunds[Sender] -= amount; + + // do we know about the receiver? + if (!m_KnownClientFunds.ContainsKey(Receiver)) + { + // Make a record for them so they get the updated balance when they login + CheckExistAndRefreshFunds(Receiver); + } + if (m_enabled) + { + //Add the amount to the Receiver's funds + m_KnownClientFunds[Receiver] += amount; + result = true; + } + } + else + { + // These below are redundant to make this clearer to read + result = false; + } + } + else + { + result = false; + } + } + else + { + result = TransferMoneyonMoneyServer(Sender, Receiver, amount, transactiontype, description); + } + } + } + return result; + } + + + /// + /// Sends the the stored money balance to the client + /// + /// + /// + /// + /// + public void SendMoneyBalance(IClientAPI client, UUID agentID, UUID SessionID, UUID TransactionID) + { + if (client.AgentId == agentID && client.SessionId == SessionID) + { + int returnfunds = 0; + + try + { + returnfunds = GetFundsForAgentID(agentID); + } + catch (Exception e) + { + client.SendAlertMessage(e.Message + " "); + } + + client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); + } + else + { + client.SendAlertMessage("Unable to send your money balance to you!"); + } + } + + /// + /// Gets the current balance for the user from the Grid Money Server + /// + /// + /// + /// + /// + /// + public Hashtable GetBalanceForUserFromMoneyServer(UUID agentId, UUID secureSessionID, UUID regionId, string regionSecret) + { + Hashtable MoneyBalanceRequestParams = new Hashtable(); + MoneyBalanceRequestParams["agentId"] = agentId.ToString(); + MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString(); + MoneyBalanceRequestParams["regionId"] = regionId.ToString(); + MoneyBalanceRequestParams["secret"] = regionSecret; + MoneyBalanceRequestParams["currencySecret"] = ""; // per - region/user currency secret gotten from the money system + + Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorUserBalanceRequest"); + + return MoneyRespData; + } + + + /// + /// Generic XMLRPC client abstraction + /// + /// Hashtable containing parameters to the method + /// Method to invoke + /// Hashtable with success=>bool and other values + public Hashtable genericCurrencyXMLRPCRequest(Hashtable ReqParams, string method) + { + ArrayList SendParams = new ArrayList(); + SendParams.Add(ReqParams); + // Send Request + XmlRpcResponse MoneyResp; + try + { + XmlRpcRequest BalanceRequestReq = new XmlRpcRequest(method, SendParams); + MoneyResp = BalanceRequestReq.Send(m_MoneyAddress, 30000); + } + catch (WebException ex) + { + m_log.ErrorFormat( + "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", + m_MoneyAddress, ex); + + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; + ErrorHash["errorURI"] = ""; + + return ErrorHash; + //throw (ex); + } + catch (SocketException ex) + { + m_log.ErrorFormat( + "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", + m_MoneyAddress, ex); + + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; + ErrorHash["errorURI"] = ""; + + return ErrorHash; + //throw (ex); + } + catch (XmlException ex) + { + m_log.ErrorFormat( + "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", + m_MoneyAddress, ex); + + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; + ErrorHash["errorURI"] = ""; + + return ErrorHash; + } + if (MoneyResp.IsFault) + { + Hashtable ErrorHash = new Hashtable(); + ErrorHash["success"] = false; + ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; + ErrorHash["errorURI"] = ""; + + return ErrorHash; + } + Hashtable MoneyRespData = (Hashtable) MoneyResp.Value; + + return MoneyRespData; + } + + /// + /// This informs the Money Grid Server that the avatar is in this simulator + /// + /// + /// + /// + /// + /// + public Hashtable claim_user(UUID agentId, UUID secureSessionID, UUID regionId, string regionSecret) + { + Hashtable MoneyBalanceRequestParams = new Hashtable(); + MoneyBalanceRequestParams["agentId"] = agentId.ToString(); + MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString(); + MoneyBalanceRequestParams["regionId"] = regionId.ToString(); + MoneyBalanceRequestParams["secret"] = regionSecret; + + Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorClaimUserRequest"); + IClientAPI sendMoneyBal = LocateClientObject(agentId); + if (sendMoneyBal != null) + { + SendMoneyBalance(sendMoneyBal, agentId, sendMoneyBal.SessionId, UUID.Zero); + } + return MoneyRespData; + } + + private SceneObjectPart findPrim(UUID objectID) + { + lock (m_scenel) + { + foreach (Scene s in m_scenel.Values) + { + SceneObjectPart part = s.GetSceneObjectPart(objectID); + if (part != null) + { + return part; + } + } + } + return null; + } + + private string resolveObjectName(UUID objectID) + { + SceneObjectPart part = findPrim(objectID); + if (part != null) + { + return part.Name; + } + return String.Empty; + } + + private string resolveAgentName(UUID agentID) + { + // try avatar username surname + Scene scene = GetRandomScene(); + CachedUserInfo profile = scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); + if (profile != null && profile.UserProfile != null) + { + string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName; + return avatarname; + } + else + { + m_log.ErrorFormat( + "[MONEY]: Could not resolve user {0}", + agentID); + } + + return String.Empty; + } + + private void BalanceUpdate(UUID senderID, UUID receiverID, bool transactionresult, string description) + { + IClientAPI sender = LocateClientObject(senderID); + IClientAPI receiver = LocateClientObject(receiverID); + + if (senderID != receiverID) + { + if (sender != null) + { + sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID)); + } + + if (receiver != null) + { + receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID)); + } + } + } + + /// + /// Informs the Money Grid Server of a transfer. + /// + /// + /// + /// + /// + public bool TransferMoneyonMoneyServer(UUID sourceId, UUID destId, int amount, int transactiontype, string description) + { + int aggregatePermInventory = 0; + int aggregatePermNextOwner = 0; + int flags = 0; + bool rvalue = false; + + IClientAPI cli = LocateClientObject(sourceId); + if (cli != null) + { + Scene userScene = null; + lock (m_rootAgents) + { + userScene = GetSceneByUUID(m_rootAgents[sourceId]); + } + if (userScene != null) + { + Hashtable ht = new Hashtable(); + ht["agentId"] = sourceId.ToString(); + ht["secureSessionId"] = cli.SecureSessionId.ToString(); + ht["regionId"] = userScene.RegionInfo.originRegionID.ToString(); + ht["secret"] = userScene.RegionInfo.regionSecret; + ht["currencySecret"] = " "; + ht["destId"] = destId.ToString(); + ht["cash"] = amount; + ht["aggregatePermInventory"] = aggregatePermInventory; + ht["aggregatePermNextOwner"] = aggregatePermNextOwner; + ht["flags"] = flags; + ht["transactionType"] = transactiontype; + ht["description"] = description; + + Hashtable hresult = genericCurrencyXMLRPCRequest(ht, "regionMoveMoney"); + + if ((bool) hresult["success"] == true) + { + int funds1 = 0; + int funds2 = 0; + try + { + funds1 = (Int32) hresult["funds"]; + } + catch (InvalidCastException) + { + funds1 = 0; + } + SetLocalFundsForAgentID(sourceId, funds1); + if (m_KnownClientFunds.ContainsKey(destId)) + { + try + { + funds2 = (Int32) hresult["funds2"]; + } + catch (InvalidCastException) + { + funds2 = 0; + } + SetLocalFundsForAgentID(destId, funds2); + } + + + rvalue = true; + } + else + { + cli.SendAgentAlertMessage((string) hresult["errorMessage"], true); + } + } + } + else + { + m_log.ErrorFormat("[MONEY]: Client {0} not found", sourceId.ToString()); + } + + return rvalue; + } + + public int GetRemoteBalance(UUID agentId) + { + int funds = 0; + + IClientAPI aClient = LocateClientObject(agentId); + if (aClient != null) + { + Scene s = LocateSceneClientIn(agentId); + if (s != null) + { + if (m_MoneyAddress.Length > 0) + { + Hashtable hbinfo = + GetBalanceForUserFromMoneyServer(aClient.AgentId, aClient.SecureSessionId, s.RegionInfo.originRegionID, + s.RegionInfo.regionSecret); + if ((bool) hbinfo["success"] == true) + { + try + { + funds = (Int32) hbinfo["funds"]; + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentId); + aClient.SendAlertMessage("Unable to get your money balance, money operations will be unavailable"); + } + catch (InvalidCastException) + { + funds = 0; + } + } + else + { + m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentId, + (string) hbinfo["errorMessage"]); + aClient.SendAlertMessage((string) hbinfo["errorMessage"]); + } + } + + SetLocalFundsForAgentID(agentId, funds); + SendMoneyBalance(aClient, agentId, aClient.SessionId, UUID.Zero); + } + else + { + m_log.Debug("[MONEY]: Got balance request update for agent that is here, but couldn't find which scene."); + } + } + else + { + m_log.Debug("[MONEY]: Got balance request update for agent that isn't here."); + } + return funds; + } + + public XmlRpcResponse GridMoneyUpdate(XmlRpcRequest request) + { + m_log.Debug("[MONEY]: Dynamic balance update called."); + Hashtable requestData = (Hashtable) request.Params[0]; + + if (requestData.ContainsKey("agentId")) + { + UUID agentId = UUID.Zero; + + UUID.TryParse((string) requestData["agentId"], out agentId); + if (agentId != UUID.Zero) + { + GetRemoteBalance(agentId); + } + else + { + m_log.Debug("[MONEY]: invalid agentId specified, dropping."); + } + } + else + { + m_log.Debug("[MONEY]: no agentId specified, dropping."); + } + XmlRpcResponse r = new XmlRpcResponse(); + Hashtable rparms = new Hashtable(); + rparms["success"] = true; + + r.Value = rparms; + return r; + } + + /// + /// XMLRPC handler to send alert message and sound to client + /// + public XmlRpcResponse UserAlert(XmlRpcRequest request) + { + XmlRpcResponse ret = new XmlRpcResponse(); + Hashtable retparam = new Hashtable(); + Hashtable requestData = (Hashtable) request.Params[0]; + + UUID agentId; + UUID soundId; + UUID regionId; + + UUID.TryParse((string) requestData["agentId"], out agentId); + UUID.TryParse((string) requestData["soundId"], out soundId); + UUID.TryParse((string) requestData["regionId"], out regionId); + string text = (string) requestData["text"]; + string secret = (string) requestData["secret"]; + + Scene userScene = GetSceneByUUID(regionId); + if (userScene != null) + { + if (userScene.RegionInfo.regionSecret == secret) + { + + IClientAPI client = LocateClientObject(agentId); + if (client != null) + { + + if (soundId != UUID.Zero) + client.SendPlayAttachedSound(soundId, UUID.Zero, UUID.Zero, 1.0f, 0); + + client.SendBlueBoxMessage(UUID.Zero, "", text); + + retparam.Add("success", true); + } + else + { + retparam.Add("success", false); + } + } + else + { + retparam.Add("success", false); + } + } + + ret.Value = retparam; + return ret; + } + + # region Standalone box enablers only + + public XmlRpcResponse quote_func(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable) request.Params[0]; + UUID agentId = UUID.Zero; + int amount = 0; + Hashtable quoteResponse = new Hashtable(); + XmlRpcResponse returnval = new XmlRpcResponse(); + + if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) + { + UUID.TryParse((string) requestData["agentId"], out agentId); + try + { + amount = (Int32) requestData["currencyBuy"]; + } + catch (InvalidCastException) + { + } + Hashtable currencyResponse = new Hashtable(); + currencyResponse.Add("estimatedCost", 0); + currencyResponse.Add("currencyBuy", amount); + + quoteResponse.Add("success", true); + quoteResponse.Add("currency", currencyResponse); + quoteResponse.Add("confirm", "asdfad9fj39ma9fj"); + + returnval.Value = quoteResponse; + return returnval; + } + + + quoteResponse.Add("success", false); + quoteResponse.Add("errorMessage", "Invalid parameters passed to the quote box"); + quoteResponse.Add("errorURI", "http://www.opensimulator.org/wiki"); + returnval.Value = quoteResponse; + return returnval; + } + + public XmlRpcResponse buy_func(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable) request.Params[0]; + UUID agentId = UUID.Zero; + int amount = 0; + if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) + { + UUID.TryParse((string) requestData["agentId"], out agentId); + try + { + amount = (Int32) requestData["currencyBuy"]; + } + catch (InvalidCastException) + { + } + if (agentId != UUID.Zero) + { + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(agentId)) + { + m_KnownClientFunds[agentId] += amount; + } + else + { + m_KnownClientFunds.Add(agentId, amount); + } + } + IClientAPI client = LocateClientObject(agentId); + if (client != null) + { + SendMoneyBalance(client, agentId, client.SessionId, UUID.Zero); + } + } + } + XmlRpcResponse returnval = new XmlRpcResponse(); + Hashtable returnresp = new Hashtable(); + returnresp.Add("success", true); + returnval.Value = returnresp; + return returnval; + } + + public XmlRpcResponse preflightBuyLandPrep_func(XmlRpcRequest request) + { + XmlRpcResponse ret = new XmlRpcResponse(); + Hashtable retparam = new Hashtable(); + Hashtable membershiplevels = new Hashtable(); + ArrayList levels = new ArrayList(); + Hashtable level = new Hashtable(); + level.Add("id", "00000000-0000-0000-0000-000000000000"); + level.Add("description", "some level"); + levels.Add(level); + //membershiplevels.Add("levels",levels); + + Hashtable landuse = new Hashtable(); + landuse.Add("upgrade", false); + landuse.Add("action", "http://invaliddomaininvalid.com/"); + + Hashtable currency = new Hashtable(); + currency.Add("estimatedCost", 0); + + Hashtable membership = new Hashtable(); + membershiplevels.Add("upgrade", false); + membershiplevels.Add("action", "http://invaliddomaininvalid.com/"); + membershiplevels.Add("levels", membershiplevels); + + retparam.Add("success", true); + retparam.Add("currency", currency); + retparam.Add("membership", membership); + retparam.Add("landuse", landuse); + retparam.Add("confirm", "asdfajsdkfjasdkfjalsdfjasdf"); + + ret.Value = retparam; + + return ret; + } + + public XmlRpcResponse landBuy_func(XmlRpcRequest request) + { + XmlRpcResponse ret = new XmlRpcResponse(); + Hashtable retparam = new Hashtable(); + Hashtable requestData = (Hashtable) request.Params[0]; + + UUID agentId = UUID.Zero; + int amount = 0; + if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) + { + UUID.TryParse((string) requestData["agentId"], out agentId); + try + { + amount = (Int32) requestData["currencyBuy"]; + } + catch (InvalidCastException) + { + } + if (agentId != UUID.Zero) + { + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(agentId)) + { + m_KnownClientFunds[agentId] += amount; + } + else + { + m_KnownClientFunds.Add(agentId, amount); + } + } + IClientAPI client = LocateClientObject(agentId); + if (client != null) + { + SendMoneyBalance(client, agentId, client.SessionId, UUID.Zero); + } + } + } + retparam.Add("success", true); + ret.Value = retparam; + + return ret; + } + + #endregion + + #region local Fund Management + + /// + /// Ensures that the agent accounting data is set up in this instance. + /// + /// + private void CheckExistAndRefreshFunds(UUID agentID) + { + lock (m_KnownClientFunds) + { + if (!m_KnownClientFunds.ContainsKey(agentID)) + { + m_KnownClientFunds.Add(agentID, m_stipend); + } + else + { + if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh) + { + m_KnownClientFunds[agentID] = m_stipend; + } + } + } + } + + /// + /// Gets the amount of Funds for an agent + /// + /// + /// + private int GetFundsForAgentID(UUID AgentID) + { + int returnfunds = 0; + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(AgentID)) + { + returnfunds = m_KnownClientFunds[AgentID]; + } + else + { + //throw new Exception("Unable to get funds."); + } + } + return returnfunds; + } + + private void SetLocalFundsForAgentID(UUID AgentID, int amount) + { + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(AgentID)) + { + m_KnownClientFunds[AgentID] = amount; + } + else + { + m_KnownClientFunds.Add(AgentID, amount); + } + } + } + + #endregion + + #region Utility Helpers + + /// + /// Locates a IClientAPI for the client specified + /// + /// + /// + private IClientAPI LocateClientObject(UUID AgentID) + { + ScenePresence tPresence = null; + IClientAPI rclient = null; + + lock (m_scenel) + { + foreach (Scene _scene in m_scenel.Values) + { + tPresence = _scene.GetScenePresence(AgentID); + if (tPresence != null) + { + if (!tPresence.IsChildAgent) + { + rclient = tPresence.ControllingClient; + } + } + if (rclient != null) + { + return rclient; + } + } + } + return null; + } + + private Scene LocateSceneClientIn(UUID AgentId) + { + lock (m_scenel) + { + foreach (Scene _scene in m_scenel.Values) + { + ScenePresence tPresence = _scene.GetScenePresence(AgentId); + if (tPresence != null) + { + if (!tPresence.IsChildAgent) + { + return _scene; + } + } + } + } + return null; + } + + /// + /// Utility function Gets a Random scene in the instance. For when which scene exactly you're doing something with doesn't matter + /// + /// + public Scene GetRandomScene() + { + lock (m_scenel) + { + foreach (Scene rs in m_scenel.Values) + return rs; + } + return null; + } + + /// + /// Utility function to get a Scene by RegionID in a module + /// + /// + /// + public Scene GetSceneByUUID(UUID RegionID) + { + lock (m_scenel) + { + foreach (Scene rs in m_scenel.Values) + { + if (rs.RegionInfo.originRegionID == RegionID) + { + return rs; + } + } + } + return null; + } + + #endregion + + #region event Handlers + + public void requestPayPrice(IClientAPI client, UUID objectID) + { + Scene scene = LocateSceneClientIn(client.AgentId); + if (scene == null) + return; + + SceneObjectPart task = scene.GetSceneObjectPart(objectID); + if (task == null) + return; + SceneObjectGroup group = task.ParentGroup; + SceneObjectPart root = group.RootPart; + + client.SendPayPrice(objectID, root.PayPrice); + } + + /// + /// When the client closes the connection we remove their accounting info from memory to free up resources. + /// + /// + public void ClientClosed(UUID AgentID) + { + lock (m_KnownClientFunds) + { + if (m_keepMoneyAcrossLogins && m_MoneyAddress.Length == 0) + { + } + else + { + m_KnownClientFunds.Remove(AgentID); + } + } + } + + /// + /// Event called Economy Data Request handler. + /// + /// + public void EconomyDataRequestHandler(UUID agentId) + { + IClientAPI user = LocateClientObject(agentId); + + if (user != null) + { + user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, + PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, + PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload, + TeleportMinPrice, TeleportPriceExponent); + } + } + + private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e) + { + if (m_MoneyAddress.Length == 0) + { + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(e.agentId)) + { + // Does the sender have enough funds to give? + if (m_KnownClientFunds[e.agentId] >= e.parcelPrice) + { + lock (e) + { + e.economyValidated = true; + } + } + } + } + } + else + { + if (GetRemoteBalance(e.agentId) >= e.parcelPrice) + { + lock (e) + { + e.economyValidated = true; + } + } + } + } + + private void processLandBuy(Object osender, EventManager.LandBuyArgs e) + { + lock (e) + { + if (e.economyValidated == true && e.transactionID == 0) + { + e.transactionID = Util.UnixTimeSinceEpoch(); + + if (doMoneyTransfer(e.agentId, e.parcelOwnerID, e.parcelPrice, 0, "Land purchase")) + { + lock (e) + { + e.amountDebited = e.parcelPrice; + } + } + } + } + } + + /// + /// THis method gets called when someone pays someone else as a gift. + /// + /// + /// + private void MoneyTransferAction(Object osender, EventManager.MoneyTransferArgs e) + { + IClientAPI sender = null; + IClientAPI receiver = null; + + if (m_MoneyAddress.Length > 0) // Handled on server + e.description = String.Empty; + + if (e.transactiontype == 5008) // Object gets paid + { + sender = LocateClientObject(e.sender); + if (sender != null) + { + SceneObjectPart part = findPrim(e.receiver); + if (part == null) + return; + + string name = resolveAgentName(part.OwnerID); + if (name == String.Empty) + name = "(hippos)"; + + receiver = LocateClientObject(part.OwnerID); + + string description = String.Format("Paid {0} via object {1}", name, e.description); + bool transactionresult = doMoneyTransfer(e.sender, part.OwnerID, e.amount, e.transactiontype, description); + + if (transactionresult) + { + ObjectPaid handlerOnObjectPaid = OnObjectPaid; + if (handlerOnObjectPaid != null) + { + handlerOnObjectPaid(e.receiver, e.sender, e.amount); + } + } + + if (e.sender != e.receiver) + { + sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.sender)); + } + if (receiver != null) + { + receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(part.OwnerID)); + } + } + return; + } + + sender = LocateClientObject(e.sender); + if (sender != null) + { + receiver = LocateClientObject(e.receiver); + + bool transactionresult = doMoneyTransfer(e.sender, e.receiver, e.amount, e.transactiontype, e.description); + + if (e.sender != e.receiver) + { + if (sender != null) + { + sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.sender)); + } + } + + if (receiver != null) + { + receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.receiver)); + } + } + else + { + m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" + + e.sender.ToString() + " Receiver: " + e.receiver.ToString() + " Amount: " + e.amount.ToString()); + } + } + + /// + /// Event Handler for when a root agent becomes a child agent + /// + /// + private void MakeChildAgent(ScenePresence avatar) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + if (m_rootAgents[avatar.UUID] == avatar.Scene.RegionInfo.originRegionID) + { + m_rootAgents.Remove(avatar.UUID); +// m_log.Debug("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); + } + } + } + } + + /// + /// Event Handler for when the client logs out. + /// + /// + private void ClientLoggedOut(UUID AgentId) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(AgentId)) + { + m_rootAgents.Remove(AgentId); + //m_log.Info("[MONEY]: Removing " + AgentId + ". Agent logged out."); + } + } + } + + /// + /// Call this when the client disconnects. + /// + /// + public void ClientClosed(IClientAPI client) + { + ClientClosed(client.AgentId); + } + + /// + /// Event Handler for when an Avatar enters one of the parcels in the simulator. + /// + /// + /// + /// + private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + if (avatar.Scene.RegionInfo.originRegionID != m_rootAgents[avatar.UUID]) + { + m_rootAgents[avatar.UUID] = avatar.Scene.RegionInfo.originRegionID; + + + //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); + // Claim User! my user! Mine mine mine! + if (m_MoneyAddress.Length > 0) + { + Scene RegionItem = GetSceneByUUID(regionID); + if (RegionItem != null) + { + Hashtable hresult = + claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret); + if ((bool)hresult["success"] == true) + { + int funds = 0; + try + { + funds = (Int32)hresult["funds"]; + } + catch (InvalidCastException) + { + } + SetLocalFundsForAgentID(avatar.UUID, funds); + } + else + { + avatar.ControllingClient.SendAgentAlertMessage((string)hresult["errorMessage"], true); + } + } + } + } + else + { + ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + if ((obj.landData.Flags & (uint)Parcel.ParcelFlags.AllowDamage) != 0) + { + avatar.Invulnerable = false; + } + else + { + avatar.Invulnerable = true; + } + } + } + else + { + lock (m_rootAgents) + { + m_rootAgents.Add(avatar.UUID, avatar.Scene.RegionInfo.originRegionID); + } + if (m_MoneyAddress.Length > 0) + { + Scene RegionItem = GetSceneByUUID(regionID); + if (RegionItem != null) + { + Hashtable hresult = claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret); + if ((bool) hresult["success"] == true) + { + int funds = 0; + try + { + funds = (Int32) hresult["funds"]; + } + catch (InvalidCastException) + { + } + SetLocalFundsForAgentID(avatar.UUID, funds); + } + else + { + avatar.ControllingClient.SendAgentAlertMessage((string) hresult["errorMessage"], true); + } + } + } + + //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); + } + } + //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); + } + + public int GetBalance(IClientAPI client) + { + GetClientFunds(client); + + lock (m_KnownClientFunds) + { + if (!m_KnownClientFunds.ContainsKey(client.AgentId)) + return 0; + + return m_KnownClientFunds[client.AgentId]; + } + } + + // Please do not refactor these to be just one method + // Existing implementations need the distinction + // + public bool UploadCovered(IClientAPI client) + { + return AmountCovered(client, PriceUpload); + } + + public bool GroupCreationCovered(IClientAPI client) + { + return AmountCovered(client, PriceGroupCreate); + } + + public bool AmountCovered(IClientAPI client, int amount) + { + if (GetBalance(client) < amount) + return false; + return true; + } + + #endregion + + public void ObjectBuy(IClientAPI remoteClient, UUID agentID, + UUID sessionID, UUID groupID, UUID categoryID, + uint localID, byte saleType, int salePrice) + { + GetClientFunds(remoteClient); + + if (!m_KnownClientFunds.ContainsKey(remoteClient.AgentId)) + { + remoteClient.SendAgentAlertMessage("Unable to buy now. Your account balance was not found.", false); + return; + } + + int funds = m_KnownClientFunds[remoteClient.AgentId]; + + if (salePrice != 0 && funds < salePrice) + { + remoteClient.SendAgentAlertMessage("Unable to buy now. You don't have sufficient funds.", false); + return; + } + + Scene s = LocateSceneClientIn(remoteClient.AgentId); + + SceneObjectPart part = s.GetSceneObjectPart(localID); + if (part == null) + { + remoteClient.SendAgentAlertMessage("Unable to buy now. The object was not found.", false); + return; + } + + if (s.PerformObjectBuy(remoteClient, categoryID, localID, saleType)) + doMoneyTransfer(remoteClient.AgentId, part.OwnerID, salePrice, 5000, "Object buy"); + } + } + + public enum TransactionType : int + { + SystemGenerated = 0, + RegionMoneyRequest = 1, + Gift = 2, + Purchase = 3 + } + + +} diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs new file mode 100644 index 0000000..7326373 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -0,0 +1,143 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Dialog +{ + public class DialogModule : IRegionModule, IDialogModule + { + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() {} + public void Close() {} + public string Name { get { return "Dialog Module"; } } + public bool IsSharedModule { get { return false; } } + + public void SendAlertToUser(IClientAPI client, string message) + { + SendAlertToUser(client, message, false); + } + + public void SendAlertToUser(IClientAPI client, string message, bool modal) + { + client.SendAgentAlertMessage(message, modal); + } + + public void SendAlertToUser(UUID agentID, string message) + { + SendAlertToUser(agentID, message, false); + } + + public void SendAlertToUser(UUID agentID, string message, bool modal) + { + ScenePresence sp = m_scene.GetScenePresence(agentID); + + if (sp != null) + sp.ControllingClient.SendAgentAlertMessage(message, modal); + } + + public void SendAlertToUser(string firstName, string lastName, string message, bool modal) + { + List presenceList = m_scene.GetScenePresences(); + + foreach (ScenePresence presence in presenceList) + { + if (presence.Firstname == firstName && presence.Lastname == lastName) + { + presence.ControllingClient.SendAgentAlertMessage(message, modal); + break; + } + } + } + + public void SendGeneralAlert(string message) + { + List presenceList = m_scene.GetScenePresences(); + + foreach (ScenePresence presence in presenceList) + { + if (!presence.IsChildAgent) + presence.ControllingClient.SendAlertMessage(message); + } + } + + public void SendDialogToUser( + UUID avatarID, string objectName, UUID objectID, UUID ownerID, + string message, UUID textureID, int ch, string[] buttonlabels) + { + ScenePresence sp = m_scene.GetScenePresence(avatarID); + + if (sp != null) + sp.ControllingClient.SendDialog(objectName, objectID, ownerID, message, textureID, ch, buttonlabels); + } + + public void SendUrlToUser( + UUID avatarID, string objectName, UUID objectID, UUID ownerID, bool groupOwned, string message, string url) + { + ScenePresence sp = m_scene.GetScenePresence(avatarID); + + if (sp != null) + sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); + } + + public void SendNotificationToUsersInEstate( + UUID fromAvatarID, string fromAvatarName, string message) + { + // TODO: This does not yet do what it says on the tin - it only sends the message to users in the same + // region as the sending avatar. + SendNotificationToUsersInRegion(fromAvatarID, fromAvatarName, message); + } + + public void SendNotificationToUsersInRegion( + UUID fromAvatarID, string fromAvatarName, string message) + { + List presenceList = m_scene.GetScenePresences(); + + foreach (ScenePresence presence in presenceList) + { + if (!presence.IsChildAgent) + presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs new file mode 100644 index 0000000..fb4d08a --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -0,0 +1,1003 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Friends +{ + /* + This module handles adding/removing friends, and the the presence + notification process for login/logoff of friends. + + The presence notification works as follows: + - After the user initially connects to a region (so we now have a UDP + connection to work with), this module fetches the friends of user + (those are cached), their on-/offline status, and info about the + region they are in from the MessageServer. + - (*) It then informs the user about the on-/offline status of her friends. + - It then informs all online friends currently on this region-server about + user's new online status (this will save some network traffic, as local + messages don't have to be transferred inter-region, and it will be all + that has to be done in Standalone Mode). + - For the rest of the online friends (those not on this region-server), + this module uses the provided region-information to map users to + regions, and sends one notification to every region containing the + friends to inform on that server. + - The region-server will handle that in the following way: + - If it finds the friend, it informs her about the user being online. + - If it doesn't find the friend (maybe she TPed away in the meantime), + it stores that information. + - After it processed all friends, it returns the list of friends it + couldn't find. + - If this list isn't empty, the FriendsModule re-requests information + about those online friends that have been missed and starts at (*) + again until all friends have been found, or until it tried 3 times + (to prevent endless loops due to some uncaught error). + + NOTE: Online/Offline notifications don't need to be sent on region change. + + We implement two XMLRpc handlers here, handling all the inter-region things + we have to handle: + - On-/Offline-Notifications (bulk) + - Terminate Friendship messages (single) + */ + + public class FriendsModule : IRegionModule, IFriendsModule + { + private class Transaction + { + public UUID agentID; + public string agentName; + public uint count; + + public Transaction(UUID agentID, string agentName) + { + this.agentID = agentID; + this.agentName = agentName; + this.count = 1; + } + } + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Cache m_friendLists = new Cache(CacheFlags.AllowUpdate); + + private Dictionary m_rootAgents = new Dictionary(); + + private Dictionary m_pendingCallingcardRequests = new Dictionary(); + + private Scene m_initialScene; // saves a lookup if we don't have a specific scene + private Dictionary m_scenes = new Dictionary(); + private IMessageTransferModule m_TransferModule = null; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_scenes) + { + if (m_scenes.Count == 0) + { + scene.CommsManager.HttpServer.AddXmlRPCHandler("presence_update_bulk", processPresenceUpdateBulk); + scene.CommsManager.HttpServer.AddXmlRPCHandler("terminate_friend", processTerminateFriend); + m_friendLists.DefaultTTL = new TimeSpan(1, 0, 0); // store entries for one hour max + m_initialScene = scene; + } + + if (!m_scenes.ContainsKey(scene.RegionInfo.RegionHandle)) + m_scenes[scene.RegionInfo.RegionHandle] = scene; + } + + scene.RegisterModuleInterface(this); + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; + scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; + scene.EventManager.OnClientClosed += ClientClosed; + } + + public void PostInitialise() + { + if (m_scenes.Count > 0) + { + m_TransferModule = m_initialScene.RequestModuleInterface(); + } + if (m_TransferModule == null) + m_log.Error("[FRIENDS]: Unable to find a message transfer module, friendship offers will not work"); + } + + public void Close() + { + } + + public string Name + { + get { return "FriendsModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + /// + /// Receive presence information changes about clients in other regions. + /// + /// + /// + public XmlRpcResponse processPresenceUpdateBulk(XmlRpcRequest req) + { + Hashtable requestData = (Hashtable)req.Params[0]; + + List friendsNotHere = new List(); + + // this is called with the expectation that all the friends in the request are on this region-server. + // But as some time passed since we checked (on the other region-server, via the MessagingServer), + // some of the friends might have teleported away. + // Actually, even now, between this line and the sending below, some people could TP away. So, + // we'll have to lock the m_rootAgents list for the duration to prevent/delay that. + lock (m_rootAgents) + { + List friendsHere = new List(); + + try + { + UUID agentID = new UUID((string)requestData["agentID"]); + bool agentOnline = (bool)requestData["agentOnline"]; + int count = (int)requestData["friendCount"]; + for (int i = 0; i < count; ++i) + { + UUID uuid; + if (UUID.TryParse((string)requestData["friendID_" + i], out uuid)) + { + if (m_rootAgents.ContainsKey(uuid)) friendsHere.Add(GetRootPresenceFromAgentID(uuid)); + else friendsNotHere.Add(uuid); + } + } + + // now send, as long as they are still here... + UUID[] agentUUID = new UUID[] { agentID }; + if (agentOnline) + { + foreach (ScenePresence agent in friendsHere) + { + agent.ControllingClient.SendAgentOnline(agentUUID); + } + } + else + { + foreach (ScenePresence agent in friendsHere) + { + agent.ControllingClient.SendAgentOffline(agentUUID); + } + } + } + catch(Exception e) + { + m_log.Warn("[FRIENDS]: Got exception while parsing presence_update_bulk request:", e); + } + } + + // no need to lock anymore; if TPs happen now, worst case is that we have an additional agent in this region, + // which should be caught on the next iteration... + Hashtable result = new Hashtable(); + int idx = 0; + foreach (UUID uuid in friendsNotHere) + { + result["friendID_" + idx++] = uuid.ToString(); + } + result["friendCount"] = idx; + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + + return response; + } + + public XmlRpcResponse processTerminateFriend(XmlRpcRequest req) + { + Hashtable requestData = (Hashtable)req.Params[0]; + + bool success = false; + + UUID agentID; + UUID friendID; + if (requestData.ContainsKey("agentID") && UUID.TryParse((string)requestData["agentID"], out agentID) && + requestData.ContainsKey("friendID") && UUID.TryParse((string)requestData["friendID"], out friendID)) + { + // try to find it and if it is there, prevent it to vanish before we sent the message + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(agentID)) + { + m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", friendID, agentID); + GetRootPresenceFromAgentID(agentID).ControllingClient.SendTerminateFriend(friendID); + success = true; + } + } + } + + // return whether we were successful + Hashtable result = new Hashtable(); + result["success"] = success; + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } + + private void OnNewClient(IClientAPI client) + { + // All friends establishment protocol goes over instant message + // There's no way to send a message from the sim + // to a user to 'add a friend' without causing dialog box spam + + // Subscribe to instant messages + client.OnInstantMessage += OnInstantMessage; + + // Friend list management + client.OnApproveFriendRequest += OnApproveFriendRequest; + client.OnDenyFriendRequest += OnDenyFriendRequest; + client.OnTerminateFriendship += OnTerminateFriendship; + + // ... calling card handling... + client.OnOfferCallingCard += OnOfferCallingCard; + client.OnAcceptCallingCard += OnAcceptCallingCard; + client.OnDeclineCallingCard += OnDeclineCallingCard; + + // we need this one exactly once per agent session (see comments in the handler below) + client.OnEconomyDataRequest += OnEconomyDataRequest; + + // if it leaves, we want to know, too + client.OnLogout += OnLogout; + } + + private void ClientClosed(UUID AgentId) + { + // agent's client was closed. As we handle logout in OnLogout, this here has only to handle + // TPing away (root agent is closed) or TPing/crossing in a region far enough away (client + // agent is closed). + // NOTE: In general, this doesn't mean that the agent logged out, just that it isn't around + // in one of the regions here anymore. + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(AgentId)) + { + m_rootAgents.Remove(AgentId); + } + } + } + + private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) + { + lock (m_rootAgents) + { + m_rootAgents[avatar.UUID] = avatar.RegionHandle; + // Claim User! my user! Mine mine mine! + } + } + + private void MakeChildAgent(ScenePresence avatar) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + // only delete if the region matches. As this is a shared module, the avatar could be + // root agent in another region on this server. + if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) + { + m_rootAgents.Remove(avatar.UUID); +// m_log.Debug("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); + } + } + } + } + + private ScenePresence GetRootPresenceFromAgentID(UUID AgentID) + { + ScenePresence returnAgent = null; + lock (m_scenes) + { + ScenePresence queryagent = null; + foreach (Scene scene in m_scenes.Values) + { + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) + { + if (!queryagent.IsChildAgent) + { + returnAgent = queryagent; + break; + } + } + } + } + return returnAgent; + } + + private ScenePresence GetAnyPresenceFromAgentID(UUID AgentID) + { + ScenePresence returnAgent = null; + lock (m_scenes) + { + ScenePresence queryagent = null; + foreach (Scene scene in m_scenes.Values) + { + queryagent = scene.GetScenePresence(AgentID); + if (queryagent != null) + { + returnAgent = queryagent; + break; + } + } + } + return returnAgent; + } + + public void OfferFriendship(UUID fromUserId, IClientAPI toUserClient, string offerMessage) + { + CachedUserInfo userInfo = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(fromUserId); + + if (userInfo != null) + { + GridInstantMessage msg = new GridInstantMessage( + toUserClient.Scene, fromUserId, userInfo.UserProfile.Name, toUserClient.AgentId, + (byte)InstantMessageDialog.FriendshipOffered, offerMessage, false, Vector3.Zero); + + FriendshipOffered(msg); + } + else + { + m_log.ErrorFormat("[FRIENDS]: No user found for id {0} in OfferFriendship()", fromUserId); + } + } + + #region FriendRequestHandling + + private void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + // Friend Requests go by Instant Message.. using the dialog param + // https://wiki.secondlife.com/wiki/ImprovedInstantMessage + + if (im.dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38 + { + // fromAgentName is the *destination* name (the friend we offer friendship to) + ScenePresence initiator = GetAnyPresenceFromAgentID(new UUID(im.fromAgentID)); + im.fromAgentName = initiator != null ? initiator.Name : "(hippo)"; + + FriendshipOffered(im); + } + else if (im.dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39 + { + FriendshipAccepted(client, im); + } + else if (im.dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40 + { + FriendshipDeclined(client, im); + } + } + + /// + /// Invoked when a user offers a friendship. + /// + /// + /// + /// + private void FriendshipOffered(GridInstantMessage im) + { + // this is triggered by the initiating agent: + // A local agent offers friendship to some possibly remote friend. + // A IM is triggered, processed here and sent to the friend (possibly in a remote region). + + m_log.DebugFormat("[FRIEND]: Offer(38) - From: {0}, FromName: {1} To: {2}, Session: {3}, Message: {4}, Offline {5}", + im.fromAgentID, im.fromAgentName, im.toAgentID, im.imSessionID, im.message, im.offline); + + // 1.20 protocol sends an UUID in the message field, instead of the friendship offer text. + // For interoperability, we have to clear that + if (Util.isUUID(im.message)) im.message = ""; + + // be sneeky and use the initiator-UUID as transactionID. This means we can be stateless. + // we have to look up the agent name on friendship-approval, though. + im.imSessionID = im.fromAgentID; + + if (m_TransferModule != null) + { + // Send it to whoever is the destination. + // If new friend is local, it will send an IM to the viewer. + // If new friend is remote, it will cause a OnGridInstantMessage on the remote server + m_TransferModule.SendInstantMessage( + im, + delegate(bool success) + { + m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); + } + ); + } + } + + /// + /// Invoked when a user accepts a friendship offer. + /// + /// + /// + private void FriendshipAccepted(IClientAPI client, GridInstantMessage im) + { + m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {2} {3}, imsession {4} to {5}: {6} (dialog {7})", + client.AgentId, im.fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog); + } + + /// + /// Invoked when a user declines a friendship offer. + /// + /// May not currently be used - see OnDenyFriendRequest() instead + /// + /// + private void FriendshipDeclined(IClientAPI client, GridInstantMessage im) + { + UUID fromAgentID = new UUID(im.fromAgentID); + UUID toAgentID = new UUID(im.toAgentID); + + // declining the friendship offer causes a type 40 IM being sent to the (possibly remote) initiator + // toAgentID is initiator, fromAgentID declined friendship + m_log.DebugFormat("[FRIEND]: 40 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})", + client != null ? client.AgentId.ToString() : "", + fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog); + + // Send the decline to whoever is the destination. + GridInstantMessage msg + = new GridInstantMessage( + client.Scene, fromAgentID, client.Name, toAgentID, + im.dialog, im.message, im.offline != 0, im.Position); + + // If new friend is local, it will send an IM to the viewer. + // If new friend is remote, it will cause a OnGridInstantMessage on the remote server + m_TransferModule.SendInstantMessage(msg, + delegate(bool success) { + m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); + } + ); + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // This event won't be raised unless we have that agent, + // so we can depend on the above not trying to send + // via grid again + m_log.DebugFormat("[FRIEND]: Got GridIM from {0}, to {1}, imSession {2}, message {3}, dialog {4}", + msg.fromAgentID, msg.toAgentID, msg.imSessionID, msg.message, msg.dialog); + + if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered || + msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted || + msg.dialog == (byte)InstantMessageDialog.FriendshipDeclined) + { + // this should succeed as we *know* the root agent is here. + m_TransferModule.SendInstantMessage(msg, + delegate(bool success) { + m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); + } + ); + } + + if (msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted) + { + // for accept friendship, we have to do a bit more + ApproveFriendship(new UUID(msg.fromAgentID), new UUID(msg.toAgentID), msg.fromAgentName); + } + } + + private void ApproveFriendship(UUID fromAgentID, UUID toAgentID, string fromName) + { + m_log.DebugFormat("[FRIEND]: Approve friendship from {0} (ID: {1}) to {2}", + fromAgentID, fromName, toAgentID); + + // a new friend was added in the initiator's and friend's data, so the cache entries are wrong now. + lock (m_friendLists) + { + m_friendLists.Invalidate(fromAgentID); + m_friendLists.Invalidate(toAgentID); + } + + // now send presence update and add a calling card for the new friend + + ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID); + if (initiator == null) + { + // quite wrong. Shouldn't happen. + m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID); + return; + } + + m_log.DebugFormat("[FRIEND]: Tell {0} that {1} is online", + initiator.Name, fromName); + // tell initiator that friend is online + initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID }); + + // find the folder for the friend... + InventoryFolderImpl folder = + initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard); + if (folder != null) + { + // ... and add the calling card + CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromName); + } + } + + private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + { + m_log.DebugFormat("[FRIEND]: Got approve friendship from {0} {1}, agentID {2}, tid {3}", + client.Name, client.AgentId, agentID, friendID); + + // store the new friend persistently for both avatars + m_initialScene.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline); + + // The cache entries aren't valid anymore either, as we just added a friend to both sides. + lock (m_friendLists) + { + m_friendLists.Invalidate(agentID); + m_friendLists.Invalidate(friendID); + } + + // if it's a local friend, we don't have to do the lookup + ScenePresence friendPresence = GetAnyPresenceFromAgentID(friendID); + + if (friendPresence != null) + { + m_log.Debug("[FRIEND]: Local agent detected."); + + // create calling card + CreateCallingCard(client, friendID, callingCardFolders[0], friendPresence.Name); + + // local message means OnGridInstantMessage won't be triggered, so do the work here. + friendPresence.ControllingClient.SendInstantMessage(agentID, agentID.ToString(), friendID, client.Name, + (byte)InstantMessageDialog.FriendshipAccepted, + (uint)Util.UnixTimeSinceEpoch()); + ApproveFriendship(agentID, friendID, client.Name); + } + else + { + m_log.Debug("[FRIEND]: Remote agent detected."); + + // fetch the friend's name for the calling card. + CachedUserInfo info = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(friendID); + + // create calling card + CreateCallingCard(client, friendID, callingCardFolders[0], + info.UserProfile.FirstName + " " + info.UserProfile.SurName); + + // Compose (remote) response to friend. + GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID, + (byte)InstantMessageDialog.FriendshipAccepted, + agentID.ToString(), false, Vector3.Zero); + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(msg, + delegate(bool success) { + m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); + } + ); + } + } + + // tell client that new friend is online + client.SendAgentOnline(new UUID[] { friendID }); + } + + private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + { + m_log.DebugFormat("[FRIEND]: Got deny friendship from {0} {1}, agentID {2}, tid {3}", + client.Name, client.AgentId, agentID, friendID); + + // Compose response to other agent. + GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID, + (byte)InstantMessageDialog.FriendshipDeclined, + agentID.ToString(), false, Vector3.Zero); + // send decline to initiator + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(msg, + delegate(bool success) { + m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); + } + ); + } + } + + private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) + { + // client.AgentId == agentID! + + // this removes the friends from the stored friendlists. After the next login, they will be gone... + m_initialScene.StoreRemoveFriendship(agentID, exfriendID); + + // ... now tell the two involved clients that they aren't friends anymore. + + // I don't know why we have to tell , as this was caused by her, but that's how it works in SL... + client.SendTerminateFriend(exfriendID); + + // now send the friend, if online + ScenePresence presence = GetAnyPresenceFromAgentID(exfriendID); + if (presence != null) + { + m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", agentID, exfriendID); + presence.ControllingClient.SendTerminateFriend(agentID); + } + else + { + // retry 3 times, in case the agent TPed from the last known region... + for (int retry = 0; retry < 3; ++retry) + { + // wasn't sent, so ex-friend wasn't around on this region-server. Fetch info and try to send + UserAgentData data = m_initialScene.CommsManager.UserService.GetAgentByUUID(exfriendID); + + if (null == data) + break; + + if (!data.AgentOnline) + { + m_log.DebugFormat("[FRIEND]: {0} is offline, so not sending TerminateFriend", exfriendID); + break; // if ex-friend isn't online, we don't need to send + } + + m_log.DebugFormat("[FRIEND]: Sending remote terminate friend {0} to agent {1}@{2}", + agentID, exfriendID, data.Handle); + + // try to send to foreign region, retry if it fails (friend TPed away, for example) + if (m_initialScene.TriggerTerminateFriend(data.Handle, exfriendID, agentID)) break; + } + } + + // clean up cache: FriendList is wrong now... + lock (m_friendLists) + { + m_friendLists.Invalidate(agentID); + m_friendLists.Invalidate(exfriendID); + } + } + + #endregion + + #region CallingCards + + private void OnOfferCallingCard(IClientAPI client, UUID destID, UUID transactionID) + { + m_log.DebugFormat("[CALLING CARD]: got offer from {0} for {1}, transaction {2}", + client.AgentId, destID, transactionID); + // This might be slightly wrong. On a multi-region server, we might get the child-agent instead of the root-agent + // (or the root instead of the child) + ScenePresence destAgent = GetAnyPresenceFromAgentID(destID); + if (destAgent == null) + { + client.SendAlertMessage("The person you have offered a card to can't be found anymore."); + return; + } + + lock (m_pendingCallingcardRequests) + { + m_pendingCallingcardRequests[transactionID] = client.AgentId; + } + // inform the destination agent about the offer + destAgent.ControllingClient.SendOfferCallingCard(client.AgentId, transactionID); + } + + private void CreateCallingCard(IClientAPI client, UUID creator, UUID folder, string name) + { + InventoryItemBase item = new InventoryItemBase(); + item.AssetID = UUID.Zero; + item.AssetType = (int)AssetType.CallingCard; + item.BasePermissions = (uint)PermissionMask.Copy; + item.CreationDate = Util.UnixTimeSinceEpoch(); + item.Creator = creator; + item.CurrentPermissions = item.BasePermissions; + item.Description = ""; + item.EveryOnePermissions = (uint)PermissionMask.None; + item.Flags = 0; + item.Folder = folder; + item.GroupID = UUID.Zero; + item.GroupOwned = false; + item.ID = UUID.Random(); + item.InvType = (int)InventoryType.CallingCard; + item.Name = name; + item.NextPermissions = item.EveryOnePermissions; + item.Owner = client.AgentId; + item.SalePrice = 10; + item.SaleType = (byte)SaleType.Not; + ((Scene)client.Scene).AddInventoryItem(client, item); + } + + private void OnAcceptCallingCard(IClientAPI client, UUID transactionID, UUID folderID) + { + m_log.DebugFormat("[CALLING CARD]: User {0} ({1} {2}) accepted tid {3}, folder {4}", + client.AgentId, + client.FirstName, client.LastName, + transactionID, folderID); + UUID destID; + lock (m_pendingCallingcardRequests) + { + if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID)) + { + m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.", + client.Name); + return; + } + // else found pending calling card request with that transaction. + m_pendingCallingcardRequests.Remove(transactionID); + } + + + ScenePresence destAgent = GetAnyPresenceFromAgentID(destID); + // inform sender of the card that destination declined the offer + if (destAgent != null) destAgent.ControllingClient.SendAcceptCallingCard(transactionID); + + // put a calling card into the inventory of receiver + CreateCallingCard(client, destID, folderID, destAgent.Name); + } + + private void OnDeclineCallingCard(IClientAPI client, UUID transactionID) + { + m_log.DebugFormat("[CALLING CARD]: User {0} (ID:{1}) declined card, tid {2}", + client.Name, client.AgentId, transactionID); + UUID destID; + lock (m_pendingCallingcardRequests) + { + if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID)) + { + m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.", + client.Name); + return; + } + // else found pending calling card request with that transaction. + m_pendingCallingcardRequests.Remove(transactionID); + } + + ScenePresence destAgent = GetAnyPresenceFromAgentID(destID); + // inform sender of the card that destination declined the offer + if (destAgent != null) destAgent.ControllingClient.SendDeclineCallingCard(transactionID); + } + + /// + /// Send presence information about a client to other clients in both this region and others. + /// + /// + /// + /// + private void SendPresenceState(IClientAPI client, List friendList, bool iAmOnline) + { + //m_log.DebugFormat("[FRIEND]: {0} logged {1}; sending presence updates", client.Name, iAmOnline ? "in" : "out"); + + if (friendList == null || friendList.Count == 0) + { + //m_log.DebugFormat("[FRIEND]: {0} doesn't have friends.", client.Name); + return; // nothing we can do if she doesn't have friends... + } + + // collect sets of friendIDs; to send to (online and offline), and to receive from + // TODO: If we ever switch to .NET >= 3, replace those Lists with HashSets. + // I can't believe that we have Dictionaries, but no Sets, considering Java introduced them years ago... + List friendIDsToSendTo = new List(); + List candidateFriendIDsToReceive = new List(); + + foreach (FriendListItem item in friendList) + { + if (((item.FriendListOwnerPerms | item.FriendPerms) & (uint)FriendRights.CanSeeOnline) != 0) + { + // friend is allowed to see my presence => add + if ((item.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0) + friendIDsToSendTo.Add(item.Friend); + + if ((item.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0) + candidateFriendIDsToReceive.Add(item.Friend); + } + } + + // we now have a list of "interesting" friends (which we have to find out on-/offline state for), + // friends we want to send our online state to (if *they* are online, too), and + // friends we want to receive online state for (currently unknown whether online or not) + + // as this processing might take some time and friends might TP away, we try up to three times to + // reach them. Most of the time, we *will* reach them, and this loop won't loop + int retry = 0; + do + { + // build a list of friends to look up region-information and on-/offline-state for + List friendIDsToLookup = new List(friendIDsToSendTo); + foreach (UUID uuid in candidateFriendIDsToReceive) + { + if (!friendIDsToLookup.Contains(uuid)) friendIDsToLookup.Add(uuid); + } + + m_log.DebugFormat( + "[FRIEND]: {0} to lookup, {1} to send to, {2} candidates to receive from for agent {3}", + friendIDsToLookup.Count, friendIDsToSendTo.Count, candidateFriendIDsToReceive.Count, client.Name); + + // we have to fetch FriendRegionInfos, as the (cached) FriendListItems don't + // necessarily contain the correct online state... + Dictionary friendRegions = m_initialScene.GetFriendRegionInfos(friendIDsToLookup); + m_log.DebugFormat( + "[FRIEND]: Found {0} regionInfos for {1} friends of {2}", + friendRegions.Count, friendIDsToLookup.Count, client.Name); + + // argument for SendAgentOn/Offline; we shouldn't generate that repeatedly within loops. + UUID[] agentArr = new UUID[] { client.AgentId }; + + // first, send to friend presence state to me, if I'm online... + if (iAmOnline) + { + List friendIDsToReceive = new List(); + + for (int i = candidateFriendIDsToReceive.Count - 1; i >= 0; --i) + { + UUID uuid = candidateFriendIDsToReceive[i]; + FriendRegionInfo info; + if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline) + { + friendIDsToReceive.Add(uuid); + } + } + + m_log.DebugFormat( + "[FRIEND]: Sending {0} online friends to {1}", friendIDsToReceive.Count, client.Name); + + if (friendIDsToReceive.Count > 0) + client.SendAgentOnline(friendIDsToReceive.ToArray()); + + // clear them for a possible second iteration; we don't have to repeat this + candidateFriendIDsToReceive.Clear(); + } + + // now, send my presence state to my friends + for (int i = friendIDsToSendTo.Count - 1; i >= 0; --i) + { + UUID uuid = friendIDsToSendTo[i]; + FriendRegionInfo info; + if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline) + { + // any client is good enough, root or child... + ScenePresence agent = GetAnyPresenceFromAgentID(uuid); + if (agent != null) + { + m_log.DebugFormat("[FRIEND]: Found local agent {0}", agent.Name); + + // friend is online and on this server... + if (iAmOnline) agent.ControllingClient.SendAgentOnline(agentArr); + else agent.ControllingClient.SendAgentOffline(agentArr); + + // done, remove it + friendIDsToSendTo.RemoveAt(i); + } + } + else + { + m_log.DebugFormat("[FRIEND]: Friend {0} ({1}) is offline; not sending.", uuid, i); + + // friend is offline => no need to try sending + friendIDsToSendTo.RemoveAt(i); + } + } + + m_log.DebugFormat("[FRIEND]: Have {0} friends to contact via inter-region comms.", friendIDsToSendTo.Count); + + // we now have all the friends left that are online (we think), but not on this region-server + if (friendIDsToSendTo.Count > 0) + { + // sort them into regions + Dictionary> friendsInRegion = new Dictionary>(); + foreach (UUID uuid in friendIDsToSendTo) + { + ulong handle = friendRegions[uuid].regionHandle; // this can't fail as we filtered above already + List friends; + if (!friendsInRegion.TryGetValue(handle, out friends)) + { + friends = new List(); + friendsInRegion[handle] = friends; + } + friends.Add(uuid); + } + m_log.DebugFormat("[FRIEND]: Found {0} regions to send to.", friendRegions.Count); + + // clear uuids list and collect missed friends in it for the next retry + friendIDsToSendTo.Clear(); + + // send bulk updates to the region + foreach (KeyValuePair> pair in friendsInRegion) + { + m_log.DebugFormat("[FRIEND]: Inform {0} friends in region {1} that user {2} is {3}line", + pair.Value.Count, pair.Key, client.Name, iAmOnline ? "on" : "off"); + + friendIDsToSendTo.AddRange(m_initialScene.InformFriendsInOtherRegion(client.AgentId, pair.Key, pair.Value, iAmOnline)); + } + } + // now we have in friendIDsToSendTo only the agents left that TPed away while we tried to contact them. + // In most cases, it will be empty, and it won't loop here. But sometimes, we have to work harder and try again... + } + while (++retry < 3 && friendIDsToSendTo.Count > 0); + } + + private void OnEconomyDataRequest(UUID agentID) + { + // KLUDGE: This is the only way I found to get a message (only) after login was completed and the + // client is connected enough to receive UDP packets). + // This packet seems to be sent only once, just after connection was established to the first + // region after login. + // We use it here to trigger a presence update; the old update-on-login was never be heard by + // the freshly logged in viewer, as it wasn't connected to the region at that time. + // TODO: Feel free to replace this by a better solution if you find one. + + // get the agent. This should work every time, as we just got a packet from it + //ScenePresence agent = GetRootPresenceFromAgentID(agentID); + // KLUDGE 2: As this is sent quite early, the avatar isn't here as root agent yet. So, we have to cheat a bit + ScenePresence agent = GetAnyPresenceFromAgentID(agentID); + + // just to be paranoid... + if (agent == null) + { + m_log.ErrorFormat("[FRIEND]: Got a packet from agent {0} who can't be found anymore!?", agentID); + return; + } + + List fl; + lock (m_friendLists) + { + fl = (List)m_friendLists.Get(agent.ControllingClient.AgentId, + m_initialScene.GetFriendList); + } + + // tell everyone that we are online + SendPresenceState(agent.ControllingClient, fl, true); + } + + private void OnLogout(IClientAPI remoteClient) + { + List fl; + lock (m_friendLists) + { + fl = (List)m_friendLists.Get(remoteClient.AgentId, + m_initialScene.GetFriendList); + } + + // tell everyone that we are offline + SendPresenceState(remoteClient, fl, false); + } + } + + #endregion +} diff --git a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs new file mode 100644 index 0000000..a3a642f --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs @@ -0,0 +1,104 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using System.Reflection; + +namespace OpenSim.Region.CoreModules.Avatar.Gestures +{ + public class GesturesModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + + m_scene.EventManager.OnNewClient += OnNewClient; + } + + public void PostInitialise() {} + public void Close() {} + public string Name { get { return "Gestures Module"; } } + public bool IsSharedModule { get { return false; } } + + private void OnNewClient(IClientAPI client) + { + client.OnActivateGesture += ActivateGesture; + client.OnDeactivateGesture += DeactivateGesture; + } + + public virtual void ActivateGesture(IClientAPI client, UUID assetId, UUID gestureId) + { + CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(client.AgentId); + + if (userInfo != null) + { + InventoryItemBase item = userInfo.RootFolder.FindItem(gestureId); + if (item != null) + { + item.Flags = 1; + userInfo.UpdateItem(item); + } + else + m_log.ErrorFormat( + "[GESTURES]: Unable to find gesture to activate {0} for {1}", gestureId, client.Name); + } + else + m_log.ErrorFormat("[GESTURES]: Unable to find user {0}", client.Name); + } + + public virtual void DeactivateGesture(IClientAPI client, UUID gestureId) + { + CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(client.AgentId); + + if (userInfo != null) + { + InventoryItemBase item = userInfo.RootFolder.FindItem(gestureId); + if (item != null) + { + item.Flags = 0; + userInfo.UpdateItem(item); + } + else + m_log.ErrorFormat( + "[GESTURES]: Unable to find gesture to deactivate {0} for {1}", gestureId, client.Name); + } + else + m_log.ErrorFormat("[GESTURES]: Unable to find user {0}", client.Name); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs new file mode 100644 index 0000000..92d0fdd --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs @@ -0,0 +1,223 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Groups +{ + public class GroupsModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary m_GroupMap = + new Dictionary(); + + private Dictionary m_ClientMap = + new Dictionary(); + + private UUID opensimulatorGroupID = + new UUID("00000000-68f9-1111-024e-222222111123"); + + private List m_SceneList = new List(); + + private static GroupMembershipData osGroup = + new GroupMembershipData(); + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + + if (groupsConfig == null) + { + m_log.Info("[GROUPS]: No configuration found. Using defaults"); + } + else + { + if (!groupsConfig.GetBoolean("Enabled", false)) + { + m_log.Info("[GROUPS]: Groups disabled in configuration"); + return; + } + + if (groupsConfig.GetString("Module", "Default") != "Default") + return; + } + + lock (m_SceneList) + { + if (!m_SceneList.Contains(scene)) + { + if (m_SceneList.Count == 0) + { + osGroup.GroupID = opensimulatorGroupID; + osGroup.GroupName = "OpenSimulator Testing"; + osGroup.GroupPowers = + (uint)(GroupPowers.AllowLandmark | + GroupPowers.AllowSetHome); + m_GroupMap[opensimulatorGroupID] = osGroup; + } + m_SceneList.Add(scene); + } + } + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnClientClosed += OnClientClosed; + scene.EventManager.OnIncomingInstantMessage += + OnGridInstantMessage; + } + + public void PostInitialise() + { + } + + public void Close() + { +// m_log.Debug("[GROUPS]: Shutting down group module."); + + lock (m_ClientMap) + { + m_ClientMap.Clear(); + } + + lock (m_GroupMap) + { + m_GroupMap.Clear(); + } + } + + public string Name + { + get { return "GroupsModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void OnNewClient(IClientAPI client) + { + // Subscribe to instant messages + client.OnInstantMessage += OnInstantMessage; + client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; + client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; + lock (m_ClientMap) + { + if (!m_ClientMap.ContainsKey(client.AgentId)) + { + m_ClientMap.Add(client.AgentId, client); + } + } + + GroupMembershipData[] updateGroups = new GroupMembershipData[1]; + updateGroups[0] = osGroup; + + client.SendGroupMembership(updateGroups); + } + + private void OnAgentDataUpdateRequest(IClientAPI remoteClient, + UUID AgentID, UUID SessionID) + { + UUID ActiveGroupID; + string ActiveGroupName; + ulong ActiveGroupPowers; + + string firstname = remoteClient.FirstName; + string lastname = remoteClient.LastName; + + string ActiveGroupTitle = "I IZ N0T"; + + ActiveGroupID = osGroup.GroupID; + ActiveGroupName = osGroup.GroupName; + ActiveGroupPowers = osGroup.GroupPowers; + + remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, + lastname, ActiveGroupPowers, ActiveGroupName, + ActiveGroupTitle); + } + + private void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Trigger the above event handler + OnInstantMessage(null, msg); + } + + private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) + { + string groupnamereply = "Unknown"; + UUID groupUUID = UUID.Zero; + + lock (m_GroupMap) + { + if (m_GroupMap.ContainsKey(id)) + { + GroupMembershipData grp = m_GroupMap[id]; + groupnamereply = grp.GroupName; + groupUUID = grp.GroupID; + } + } + remote_client.SendGroupNameReply(groupUUID, groupnamereply); + } + + private void OnClientClosed(UUID agentID) + { + lock (m_ClientMap) + { + if (m_ClientMap.ContainsKey(agentID)) + { +// IClientAPI cli = m_ClientMap[agentID]; +// if (cli != null) +// { +// //m_log.Info("[GROUPS]: Removing all reference to groups for " + cli.Name); +// } +// else +// { +// //m_log.Info("[GROUPS]: Removing all reference to groups for " + agentID.ToString()); +// } + m_ClientMap.Remove(agentID); + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs new file mode 100644 index 0000000..3ad2c91 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs @@ -0,0 +1,170 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Net; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.InstantMessage +{ + public class InstantMessageModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Is this module enabled? + /// + private bool m_enabled = false; + + private readonly List m_scenes = new List(); + + #region IRegionModule Members + + private IMessageTransferModule m_TransferModule = null; + + public void Initialise(Scene scene, IConfigSource config) + { + if (config.Configs["Messaging"] != null) + { + if (config.Configs["Messaging"].GetString( + "InstantMessageModule", "InstantMessageModule") != + "InstantMessageModule") + return; + } + + m_enabled = true; + + lock (m_scenes) + { + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnClientConnect += OnClientConnect; + scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; + } + } + } + + void OnClientConnect(IClientCore client) + { + IClientIM clientIM; + if (client.TryGet(out clientIM)) + { + clientIM.OnInstantMessage += OnInstantMessage; + } + } + + public void PostInitialise() + { + if (!m_enabled) + return; + + m_TransferModule = + m_scenes[0].RequestModuleInterface(); + + if (m_TransferModule == null) + m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+ + "IM will not work!"); + } + + public void Close() + { + } + + public string Name + { + get { return "InstantMessageModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + public void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + byte dialog = im.dialog; + + if ( dialog != (byte)InstantMessageDialog.MessageFromAgent + && dialog != (byte)InstantMessageDialog.StartTyping + && dialog != (byte)InstantMessageDialog.StopTyping) + { + return; + } + + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(im, + delegate(bool success) + { + if (dialog == (uint)InstantMessageDialog.StartTyping || + dialog == (uint)InstantMessageDialog.StopTyping) + { + return; + } + + if ((client != null) && !success) + { + client.SendInstantMessage(new UUID(im.toAgentID), + "Unable to send instant message. "+ + "User is not logged in.", + new UUID(im.fromAgentID), "System", + (byte)InstantMessageDialog.BusyAutoResponse, + (uint)Util.UnixTimeSinceEpoch()); + } + } + ); + } + } + + /// + /// + /// + /// + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Just call the Text IM handler above + // This event won't be raised unless we have that agent, + // so we can depend on the above not trying to send + // via grid again + // + OnInstantMessage(null, msg); + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs new file mode 100644 index 0000000..91c22eb --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -0,0 +1,655 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Net; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.InstantMessage +{ + public class MessageTransferModule : IRegionModule, IMessageTransferModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // private bool m_Enabled = false; + private bool m_Gridmode = false; + private List m_Scenes = new List(); + private Dictionary m_UserRegionMap = new Dictionary(); + + public void Initialise(Scene scene, IConfigSource config) + { + IConfig cnf = config.Configs["Messaging"]; + if (cnf != null && cnf.GetString( + "MessageTransferModule", "MessageTransferModule") != + "MessageTransferModule") + return; + + cnf = config.Configs["Startup"]; + if (cnf != null) + m_Gridmode = cnf.GetBoolean("gridmode", false); + + // m_Enabled = true; + + lock (m_Scenes) + { + if (m_Scenes.Count == 0) + { + scene.CommsManager.HttpServer.AddXmlRPCHandler( + "grid_instant_message", processXMLRPCGridInstantMessage); + } + + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "MessageTransferModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) + { + UUID toAgentID = new UUID(im.toAgentID); + + m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); + + // Try root avatar only first + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); + // Local message + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + if (!user.IsChildAgent) + { + m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); + user.ControllingClient.SendInstantMessage( + new UUID(im.fromAgentID), + im.message, + new UUID(im.toAgentID), + im.fromAgentName, + im.dialog, + im.timestamp, + new UUID(im.imSessionID), + im.fromGroup, + im.binaryBucket); + // Message sent + result(true); + return; + } + } + } + + // try child avatar second + foreach (Scene scene in m_Scenes) + { +// m_log.DebugFormat( +// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); + + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + + m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); + user.ControllingClient.SendInstantMessage( + new UUID(im.fromAgentID), + im.message, + new UUID(im.toAgentID), + im.fromAgentName, + im.dialog, + im.timestamp, + new UUID(im.imSessionID), + im.fromGroup, + im.binaryBucket); + // Message sent + result(true); + return; + } + } + + if (m_Gridmode) + { + //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid"); + // Still here, try send via Grid + SendGridInstantMessageViaXMLRPC(im, result); + return; + } + + //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); + result(false); + return; + } + + /// + /// Process a XMLRPC Grid Instant Message + /// + /// XMLRPC parameters + /// + /// Nothing much + protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request) + { + bool successful = false; + + // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that + // happen here and aren't caught and log them. + try + { + // various rational defaults + UUID fromAgentID = UUID.Zero; + UUID toAgentID = UUID.Zero; + UUID imSessionID = UUID.Zero; + uint timestamp = 0; + string fromAgentName = ""; + string message = ""; + byte dialog = (byte)0; + bool fromGroup = false; + byte offline = (byte)0; + uint ParentEstateID=0; + Vector3 Position = Vector3.Zero; + UUID RegionID = UUID.Zero ; + byte[] binaryBucket = new byte[0]; + + float pos_x = 0; + float pos_y = 0; + float pos_z = 0; + //m_log.Info("Processing IM"); + + + Hashtable requestData = (Hashtable)request.Params[0]; + // Check if it's got all the data + if (requestData.ContainsKey("from_agent_id") + && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id") + && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name") + && requestData.ContainsKey("message") && requestData.ContainsKey("dialog") + && requestData.ContainsKey("from_group") + && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id") + && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y") + && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") + && requestData.ContainsKey("binary_bucket")) + { + // Do the easy way of validating the UUIDs + UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); + UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); + UUID.TryParse((string)requestData["im_session_id"], out imSessionID); + UUID.TryParse((string)requestData["region_id"], out RegionID); + + try + { + timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + fromAgentName = (string)requestData["from_agent_name"]; + message = (string)requestData["message"]; + + // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them. + string requestData1 = (string)requestData["dialog"]; + if (string.IsNullOrEmpty(requestData1)) + { + dialog = 0; + } + else + { + byte[] dialogdata = Convert.FromBase64String(requestData1); + dialog = dialogdata[0]; + } + + if ((string)requestData["from_group"] == "TRUE") + fromGroup = true; + + string requestData2 = (string)requestData["offline"]; + if (String.IsNullOrEmpty(requestData2)) + { + offline = 0; + } + else + { + byte[] offlinedata = Convert.FromBase64String(requestData2); + offline = offlinedata[0]; + } + + try + { + ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + try + { + pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + try + { + pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + try + { + pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + Position = new Vector3(pos_x, pos_y, pos_z); + + string requestData3 = (string)requestData["binary_bucket"]; + if (string.IsNullOrEmpty(requestData3)) + { + binaryBucket = new byte[0]; + } + else + { + binaryBucket = Convert.FromBase64String(requestData3); + } + + // Create a New GridInstantMessageObject the the data + GridInstantMessage gim = new GridInstantMessage(); + gim.fromAgentID = fromAgentID.Guid; + gim.fromAgentName = fromAgentName; + gim.fromGroup = fromGroup; + gim.imSessionID = imSessionID.Guid; + gim.RegionID = RegionID.Guid; + gim.timestamp = timestamp; + gim.toAgentID = toAgentID.Guid; + gim.message = message; + gim.dialog = dialog; + gim.offline = offline; + gim.ParentEstateID = ParentEstateID; + gim.Position = Position; + gim.binaryBucket = binaryBucket; + + + // Trigger the Instant message in the scene. + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + ScenePresence user = + (ScenePresence)scene.Entities[toAgentID]; + + if (!user.IsChildAgent) + { + scene.EventManager.TriggerIncomingInstantMessage(gim); + successful = true; + } + } + } + if (!successful) + { + // If the message can't be delivered to an agent, it + // is likely to be a group IM. On a group IM, the + // imSessionID = toAgentID = group id. Raise the + // unhandled IM event to give the groups module + // a chance to pick it up. We raise that in a random + // scene, since the groups module is shared. + // + m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim); + } + } + } + catch (Exception e) + { + m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e); + successful = false; + } + + //Send response back to region calling if it was successful + // calling region uses this to know when to look up a user's location again. + XmlRpcResponse resp = new XmlRpcResponse(); + Hashtable respdata = new Hashtable(); + if (successful) + respdata["success"] = "TRUE"; + else + respdata["success"] = "FALSE"; + resp.Value = respdata; + + return resp; + } + + /// + /// delegate for sending a grid instant message asynchronously + /// + public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle); + + private void GridInstantMessageCompleted(IAsyncResult iar) + { + GridInstantMessageDelegate icon = + (GridInstantMessageDelegate)iar.AsyncState; + icon.EndInvoke(iar); + } + + + protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) + { + GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; + + d.BeginInvoke(im, result, 0, GridInstantMessageCompleted, d); + } + + /// + /// Recursive SendGridInstantMessage over XMLRPC method. + /// This is called from within a dedicated thread. + /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from + /// itself, prevRegionHandle will be the last region handle that we tried to send. + /// If the handles are the same, we look up the user's location using the grid. + /// If the handles are still the same, we end. The send failed. + /// + /// + /// Pass in 0 the first time this method is called. It will be called recursively with the last + /// regionhandle tried + /// + protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle) + { + UUID toAgentID = new UUID(im.toAgentID); + + UserAgentData upd = null; + + bool lookupAgent = false; + + lock (m_UserRegionMap) + { + if (m_UserRegionMap.ContainsKey(toAgentID)) + { + upd = new UserAgentData(); + upd.AgentOnline = true; + upd.Handle = m_UserRegionMap[toAgentID]; + + // We need to compare the current regionhandle with the previous region handle + // or the recursive loop will never end because it will never try to lookup the agent again + if (prevRegionHandle == upd.Handle) + { + lookupAgent = true; + } + } + else + { + lookupAgent = true; + } + } + + + // Are we needing to look-up an agent? + if (lookupAgent) + { + // Non-cached user agent lookup. + upd = m_Scenes[0].CommsManager.UserService.GetAgentByUUID(toAgentID); + + if (upd != null) + { + // check if we've tried this before.. + // This is one way to end the recursive loop + // + if (upd.Handle == prevRegionHandle) + { + m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + result(false); + return; + } + } + else + { + m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + result(false); + return; + } + } + + if (upd != null) + { + if (upd.AgentOnline) + { + RegionInfo reginfo = m_Scenes[0].SceneGridService.RequestNeighbouringRegionInfo(upd.Handle); + if (reginfo != null) + { + Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); + // Not actually used anymore, left in for compatibility + // Remove at next interface change + // + msgdata["region_handle"] = 0; + bool imresult = doIMSending(reginfo, msgdata); + if (imresult) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserRegionMap) + { + if (m_UserRegionMap.ContainsKey(toAgentID)) + { + m_UserRegionMap[toAgentID] = upd.Handle; + } + else + { + m_UserRegionMap.Add(toAgentID, upd.Handle); + } + } + result(true); + } + else + { + // try again, but lookup user this time. + // Warning, this must call the Async version + // of this method or we'll be making thousands of threads + // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync + // The version that spawns the thread is SendGridInstantMessageViaXMLRPC + + // This is recursive!!!!! + SendGridInstantMessageViaXMLRPCAsync(im, result, + upd.Handle); + } + + } + else + { + m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.Handle); + result(false); + } + } + else + { + result(false); + } + } + else + { + m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find user {0}", toAgentID); + result(false); + } + + } + + /// + /// This actually does the XMLRPC Request + /// + /// RegionInfo we pull the data out of to send the request to + /// The Instant Message data Hashtable + /// Bool if the message was successfully delivered at the other side. + private bool doIMSending(RegionInfo reginfo, Hashtable xmlrpcdata) + { + + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); + try + { + + XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); + + Hashtable responseData = (Hashtable)GridResp.Value; + + if (responseData.ContainsKey("success")) + { + if ((string)responseData["success"] == "TRUE") + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + catch (WebException e) + { + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})", + reginfo.ExternalHostName, reginfo.HttpPort, e.Message); + } + + return false; + } + + /// + /// Get ulong region handle for region by it's Region UUID. + /// We use region handles over grid comms because there's all sorts of free and cool caching. + /// + /// UUID of region to get the region handle for + /// +// private ulong getLocalRegionHandleFromUUID(UUID regionID) +// { +// ulong returnhandle = 0; +// +// lock (m_Scenes) +// { +// foreach (Scene sn in m_Scenes) +// { +// if (sn.RegionInfo.RegionID == regionID) +// { +// returnhandle = sn.RegionInfo.RegionHandle; +// break; +// } +// } +// } +// return returnhandle; +// } + + /// + /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC + /// + /// The GridInstantMessage object + /// Hashtable containing the XMLRPC request + private Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg) + { + Hashtable gim = new Hashtable(); + gim["from_agent_id"] = msg.fromAgentID.ToString(); + // Kept for compatibility + gim["from_agent_session"] = UUID.Zero.ToString(); + gim["to_agent_id"] = msg.toAgentID.ToString(); + gim["im_session_id"] = msg.imSessionID.ToString(); + gim["timestamp"] = msg.timestamp.ToString(); + gim["from_agent_name"] = msg.fromAgentName; + gim["message"] = msg.message; + byte[] dialogdata = new byte[1];dialogdata[0] = msg.dialog; + gim["dialog"] = Convert.ToBase64String(dialogdata,Base64FormattingOptions.None); + + if (msg.fromGroup) + gim["from_group"] = "TRUE"; + else + gim["from_group"] = "FALSE"; + byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline; + gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None); + gim["parent_estate_id"] = msg.ParentEstateID.ToString(); + gim["position_x"] = msg.Position.X.ToString(); + gim["position_y"] = msg.Position.Y.ToString(); + gim["position_z"] = msg.Position.Z.ToString(); + gim["region_id"] = msg.RegionID.ToString(); + gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); + return gim; + } + + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs new file mode 100644 index 0000000..49fd70a --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs @@ -0,0 +1,426 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Net; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.InstantMessage +{ + public class PresenceModule : IRegionModule, IPresenceModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_Enabled = false; + private bool m_Gridmode = false; + + // some default scene for doing things that aren't connected to a specific scene. Avoids locking. + private Scene m_initialScene; + + private List m_Scenes = new List(); + + // we currently are only interested in root-agents. If the root isn't here, we don't know the region the + // user is in, so we have to ask the messaging server anyway. + private Dictionary m_RootAgents = + new Dictionary(); + + public event PresenceChange OnPresenceChange; + public event BulkPresenceData OnBulkPresenceData; + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_Scenes) + { + // This is a shared module; Initialise will be called for every region on this server. + // Only check config once for the first region. + if (m_Scenes.Count == 0) + { + IConfig cnf = config.Configs["Messaging"]; + if (cnf != null && cnf.GetString( + "PresenceModule", "PresenceModule") != + "PresenceModule") + return; + + cnf = config.Configs["Startup"]; + if (cnf != null) + m_Gridmode = cnf.GetBoolean("gridmode", false); + + m_Enabled = true; + + m_initialScene = scene; + } + + if (m_Gridmode) + NotifyMessageServerOfStartup(scene); + + m_Scenes.Add(scene); + } + + scene.RegisterModuleInterface(this); + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; + scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; + } + + public void PostInitialise() + { + } + + public void Close() + { + if (!m_Gridmode || !m_Enabled) + return; + + if (OnPresenceChange != null) + { + lock (m_RootAgents) + { + // on shutdown, users are kicked, too + foreach (KeyValuePair pair in m_RootAgents) + { + OnPresenceChange(new PresenceInfo(pair.Key, UUID.Zero)); + } + } + } + + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + NotifyMessageServerOfShutdown(scene); + } + } + + public string Name + { + get { return "PresenceModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void RequestBulkPresenceData(UUID[] users) + { + if (OnBulkPresenceData != null) + { + PresenceInfo[] result = new PresenceInfo[users.Length]; + if (m_Gridmode) + { + // first check the local information + List uuids = new List(); // the uuids to check remotely + List indices = new List(); // just for performance. + lock (m_RootAgents) + { + for (int i = 0; i < uuids.Count; ++i) + { + Scene scene; + if (m_RootAgents.TryGetValue(users[i], out scene)) + { + result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID); + } + else + { + uuids.Add(users[i]); + indices.Add(i); + } + } + } + + // now we have filtered out all the local root agents. The rest we have to request info about + Dictionary infos = m_initialScene.GetFriendRegionInfos(uuids); + for (int i = 0; i < uuids.Count; ++i) + { + FriendRegionInfo info; + if (infos.TryGetValue(uuids[i], out info) && info.isOnline) + { + UUID regionID = info.regionID; + if (regionID == UUID.Zero) + { + // TODO this is the old messaging-server protocol; only the regionHandle is available. + // Fetch region-info to get the id + RegionInfo regionInfo = m_initialScene.RequestNeighbouringRegionInfo(info.regionHandle); + regionID = regionInfo.RegionID; + } + result[indices[i]] = new PresenceInfo(uuids[i], regionID); + } + else result[indices[i]] = new PresenceInfo(uuids[i], UUID.Zero); + } + } + else + { + // in standalone mode, we have all the info locally available. + lock (m_RootAgents) + { + for (int i = 0; i < users.Length; ++i) + { + Scene scene; + if (m_RootAgents.TryGetValue(users[i], out scene)) + { + result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID); + } + else + { + result[i] = new PresenceInfo(users[i], UUID.Zero); + } + } + } + } + + // tell everyone + OnBulkPresenceData(result); + } + } + + // new client doesn't mean necessarily that user logged in, it just means it entered one of the + // the regions on this server + public void OnNewClient(IClientAPI client) + { + client.OnConnectionClosed += OnConnectionClosed; + client.OnLogout += OnLogout; + + // KLUDGE: See handler for details. + client.OnEconomyDataRequest += OnEconomyDataRequest; + } + + // connection closed just means *one* client connection has been closed. It doesn't mean that the + // user has logged off; it might have just TPed away. + public void OnConnectionClosed(IClientAPI client) + { + // TODO: Have to think what we have to do here... + // Should we just remove the root from the list (if scene matches)? + if (!(client.Scene is Scene)) + return; + Scene scene = (Scene)client.Scene; + + lock (m_RootAgents) + { + Scene rootScene; + if (!(m_RootAgents.TryGetValue(client.AgentId, out rootScene)) || scene != rootScene) + return; + + m_RootAgents.Remove(client.AgentId); + } + + // Should it have logged off, we'll do the logout part in OnLogout, even if no root is stored + // anymore. It logged off, after all... + } + + // Triggered when the user logs off. + public void OnLogout(IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + Scene scene = (Scene)client.Scene; + + // On logout, we really remove the client from rootAgents, even if the scene doesn't match + lock (m_RootAgents) + { + if (m_RootAgents.ContainsKey(client.AgentId)) m_RootAgents.Remove(client.AgentId); + } + + // now inform the messaging server and anyone who is interested + NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); + if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(client.AgentId, UUID.Zero)); + } + + public void OnSetRootAgentScene(UUID agentID, Scene scene) + { + // OnSetRootAgentScene can be called from several threads at once (with different agentID). + // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without + // correct locking). + lock (m_RootAgents) + { + Scene rootScene; + if (m_RootAgents.TryGetValue(agentID, out rootScene) && scene == rootScene) + { + return; + } + m_RootAgents[agentID] = scene; + } + // inform messaging server that agent changed the region + NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); + } + + private void OnEconomyDataRequest(UUID agentID) + { + // KLUDGE: This is the only way I found to get a message (only) after login was completed and the + // client is connected enough to receive UDP packets. + // This packet seems to be sent only once, just after connection was established to the first + // region after login. + // We use it here to trigger a presence update; the old update-on-login was never be heard by + // the freshly logged in viewer, as it wasn't connected to the region at that time. + // TODO: Feel free to replace this by a better solution if you find one. + + // get the agent. This should work every time, as we just got a packet from it + ScenePresence agent = null; + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + { + agent = scene.GetScenePresence(agentID); + if (agent != null) break; + } + } + + // just to be paranoid... + if (agent == null) + { + m_log.ErrorFormat("[PRESENCE]: Got a packet from agent {0} who can't be found anymore!?", agentID); + return; + } + + // we are a bit premature here, but the next packet will switch this child agent to root. + if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(agentID, agent.Scene.RegionInfo.RegionID)); + } + + public void OnMakeChildAgent(ScenePresence agent) + { + // OnMakeChildAgent can be called from several threads at once (with different agent). + // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without + // correct locking). + lock (m_RootAgents) + { + Scene rootScene; + if (m_RootAgents.TryGetValue(agent.UUID, out rootScene) && agent.Scene == rootScene) + { + m_RootAgents.Remove(agent.UUID); + } + } + // don't notify the messaging-server; either this agent just had been downgraded and another one will be upgraded + // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment, + // which will update the messaging-server, too. + } + + private void NotifyMessageServerOfStartup(Scene scene) + { + Hashtable xmlrpcdata = new Hashtable(); + xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString(); + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + try + { + XmlRpcRequest UpRequest = new XmlRpcRequest("region_startup", SendParams); + XmlRpcResponse resp = UpRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000); + + Hashtable responseData = (Hashtable)resp.Value; + if (responseData == null || (!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName); + } + } + catch (System.Net.WebException) + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName); + } + } + + private void NotifyMessageServerOfShutdown(Scene scene) + { + Hashtable xmlrpcdata = new Hashtable(); + xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString(); + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + try + { + XmlRpcRequest DownRequest = new XmlRpcRequest("region_shutdown", SendParams); + XmlRpcResponse resp = DownRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000); + + Hashtable responseData = (Hashtable)resp.Value; + if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName); + } + } + catch (System.Net.WebException) + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName); + } + } + + private void NotifyMessageServerOfAgentLocation(UUID agentID, UUID region, ulong regionHandle) + { + Hashtable xmlrpcdata = new Hashtable(); + xmlrpcdata["AgentID"] = agentID.ToString(); + xmlrpcdata["RegionUUID"] = region.ToString(); + xmlrpcdata["RegionHandle"] = regionHandle.ToString(); + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + try + { + XmlRpcRequest LocationRequest = new XmlRpcRequest("agent_location", SendParams); + XmlRpcResponse resp = LocationRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000); + + Hashtable responseData = (Hashtable)resp.Value; + if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString()); + } + } + catch (System.Net.WebException) + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString()); + } + } + + private void NotifyMessageServerOfAgentLeaving(UUID agentID, UUID region, ulong regionHandle) + { + Hashtable xmlrpcdata = new Hashtable(); + xmlrpcdata["AgentID"] = agentID.ToString(); + xmlrpcdata["RegionUUID"] = region.ToString(); + xmlrpcdata["RegionHandle"] = regionHandle.ToString(); + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + try + { + XmlRpcRequest LeavingRequest = new XmlRpcRequest("agent_leaving", SendParams); + XmlRpcResponse resp = LeavingRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000); + + Hashtable responseData = (Hashtable)resp.Value; + if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString()); + } + } + catch (System.Net.WebException) + { + m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString()); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs new file mode 100644 index 0000000..49006a2 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -0,0 +1,279 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using System.Xml; +using OpenMetaverse; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Archiver; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using log4net; + + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver +{ + public class InventoryArchiveReadRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene scene; + protected TarArchiveReader archive; + private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); + + CommunicationsManager commsManager; + + public InventoryArchiveReadRequest(Scene currentScene, CommunicationsManager commsManager) + { + //List serialisedObjects = new List(); + scene = currentScene; + this.commsManager = commsManager; + } + + protected InventoryItemBase loadInvItem(string path, string contents) + { + InventoryItemBase item = new InventoryItemBase(); + StringReader sr = new StringReader(contents); + XmlTextReader reader = new XmlTextReader(sr); + + if (contents.Equals("")) return null; + + reader.ReadStartElement("InventoryObject"); + reader.ReadStartElement("Name"); + item.Name = reader.ReadString(); + reader.ReadEndElement(); + reader.ReadStartElement("ID"); + item.ID = UUID.Parse(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("InvType"); + item.InvType = System.Convert.ToInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("CreatorUUID"); + item.Creator = UUID.Parse(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("CreationDate"); + item.CreationDate = System.Convert.ToInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("Owner"); + item.Owner = UUID.Parse(reader.ReadString()); + reader.ReadEndElement(); + //No description would kill it + if (reader.IsEmptyElement) + { + reader.ReadStartElement("Description"); + } + else + { + reader.ReadStartElement("Description"); + item.Description = reader.ReadString(); + reader.ReadEndElement(); + } + reader.ReadStartElement("AssetType"); + item.AssetType = System.Convert.ToInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("AssetID"); + item.AssetID = UUID.Parse(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("SaleType"); + item.SaleType = System.Convert.ToByte(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("SalePrice"); + item.SalePrice = System.Convert.ToInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("BasePermissions"); + item.BasePermissions = System.Convert.ToUInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("CurrentPermissions"); + item.CurrentPermissions = System.Convert.ToUInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("EveryOnePermssions"); + item.EveryOnePermissions = System.Convert.ToUInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("NextPermissions"); + item.NextPermissions = System.Convert.ToUInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("Flags"); + item.Flags = System.Convert.ToUInt32(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("GroupID"); + item.GroupID = UUID.Parse(reader.ReadString()); + reader.ReadEndElement(); + reader.ReadStartElement("GroupOwned"); + item.GroupOwned = System.Convert.ToBoolean(reader.ReadString()); + reader.ReadEndElement(); + //reader.ReadStartElement("ParentFolderID"); + //item.Folder = UUID.Parse(reader.ReadString()); + //reader.ReadEndElement(); + //reader.ReadEndElement(); + + return item; + } + + public void execute(string firstName, string lastName, string invPath, string loadPath) + { + string filePath = "ERROR"; + int successfulAssetRestores = 0; + int failedAssetRestores = 0; + int successfulItemRestores = 0; + + UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName); + if (null == userProfile) + { + m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName); + return; + } + + CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID); + if (null == userInfo) + { + m_log.ErrorFormat( + "[CONSOLE]: Failed to find user info for {0} {1} {2}", + firstName, lastName, userProfile.ID); + + return; + } + + if (!userInfo.HasReceivedInventory) + { + m_log.ErrorFormat( + "[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}", + firstName, lastName, userProfile.ID); + + return; + } + + InventoryFolderImpl inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath); + + if (null == inventoryFolder) + { + // TODO: Later on, automatically create this folder if it does not exist + m_log.ErrorFormat("[ARCHIVER]: Inventory path {0} does not exist", invPath); + + return; + } + + archive + = new TarArchiveReader(new GZipStream( + new FileStream(loadPath, FileMode.Open), CompressionMode.Decompress)); + + byte[] data; + TarArchiveReader.TarEntryType entryType; + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + { + if (entryType == TarArchiveReader.TarEntryType.TYPE_DIRECTORY) { + m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", filePath); + } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + if (LoadAsset(filePath, data)) + successfulAssetRestores++; + else + failedAssetRestores++; + } + else + { + InventoryItemBase item = loadInvItem(filePath, m_asciiEncoding.GetString(data)); + + if (item != null) + { + item.Creator = userProfile.ID; + item.Owner = userProfile.ID; + + // Reset folder ID to the one in which we want to load it + // TODO: Properly restore entire folder structure. At the moment all items are dumped in this + // single folder no matter where in the saved folder structure they are. + item.Folder = inventoryFolder.ID; + + userInfo.AddItem(item); + successfulItemRestores++; + } + } + } + + archive.Close(); + + m_log.DebugFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); + m_log.InfoFormat("[ARCHIVER]: Restored {0} items", successfulItemRestores); + } + + /// + /// Load an asset + /// + /// + /// + /// true if asset was successfully loaded, false otherwise + private bool LoadAsset(string assetPath, byte[] data) + { + //IRegionSerialiser serialiser = scene.RequestModuleInterface(); + // Right now we're nastily obtaining the UUID from the filename + string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); + int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR); + + if (i == -1) + { + m_log.ErrorFormat( + "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping", + assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR); + + return false; + } + + string extension = filename.Substring(i); + string uuid = filename.Remove(filename.Length - extension.Length); + + if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) + { + sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; + + m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); + + AssetBase asset = new AssetBase(new UUID(uuid), "RandomName"); + + asset.Metadata.Type = assetType; + asset.Data = data; + + scene.AssetCache.AddAsset(asset); + + + return true; + } + else + { + m_log.ErrorFormat( + "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}", + assetPath, extension); + + return false; + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs new file mode 100644 index 0000000..f548296 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -0,0 +1,247 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using System.Xml; +using OpenMetaverse; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Archiver; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using log4net; + + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver +{ + public class InventoryArchiveWriteRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene scene; + protected TarArchiveWriter archive; + protected CommunicationsManager commsManager; + Dictionary assetUuids; + + /// + /// The path to which the inventory archive will be saved. + /// + private string m_savePath; + + public InventoryArchiveWriteRequest(Scene currentScene, CommunicationsManager commsManager) + { + scene = currentScene; + archive = new TarArchiveWriter(); + this.commsManager = commsManager; + assetUuids = new Dictionary(); + } + + protected void ReceivedAllAssets(IDictionary assetsFound, ICollection assetsNotFoundUuids) + { + AssetsArchiver assetsArchiver = new AssetsArchiver(assetsFound); + assetsArchiver.Archive(archive); + archive.WriteTar(new GZipStream(new FileStream(m_savePath, FileMode.Create), CompressionMode.Compress)); + } + + protected void saveInvItem(InventoryItemBase inventoryItem, string path) + { + string filename + = string.Format("{0}{1}_{2}.xml", + path, inventoryItem.Name, inventoryItem.ID); + StringWriter sw = new StringWriter(); + XmlTextWriter writer = new XmlTextWriter(sw); + writer.WriteStartElement("InventoryObject"); + writer.WriteStartElement("Name"); + writer.WriteString(inventoryItem.Name); + writer.WriteEndElement(); + writer.WriteStartElement("ID"); + writer.WriteString(inventoryItem.ID.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("InvType"); + writer.WriteString(inventoryItem.InvType.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("CreatorUUID"); + writer.WriteString(inventoryItem.Creator.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("CreationDate"); + writer.WriteString(inventoryItem.CreationDate.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("Owner"); + writer.WriteString(inventoryItem.Owner.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("Description"); + if (inventoryItem.Description.Length > 0) + writer.WriteString(inventoryItem.Description); + else writer.WriteString("No Description"); + writer.WriteEndElement(); + writer.WriteStartElement("AssetType"); + writer.WriteString(inventoryItem.AssetType.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("AssetID"); + writer.WriteString(inventoryItem.AssetID.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("SaleType"); + writer.WriteString(inventoryItem.SaleType.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("SalePrice"); + writer.WriteString(inventoryItem.SalePrice.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("BasePermissions"); + writer.WriteString(inventoryItem.BasePermissions.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("CurrentPermissions"); + writer.WriteString(inventoryItem.CurrentPermissions.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("EveryOnePermssions"); + writer.WriteString(inventoryItem.EveryOnePermissions.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("NextPermissions"); + writer.WriteString(inventoryItem.NextPermissions.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("Flags"); + writer.WriteString(inventoryItem.Flags.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("GroupID"); + writer.WriteString(inventoryItem.GroupID.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("GroupOwned"); + writer.WriteString(inventoryItem.GroupOwned.ToString()); + writer.WriteEndElement(); + writer.WriteStartElement("ParentFolderID"); + writer.WriteString(inventoryItem.Folder.ToString()); + writer.WriteEndElement(); + writer.WriteEndElement(); + + archive.AddFile(filename, sw.ToString()); + + assetUuids[inventoryItem.AssetID] = 1; + } + + protected void saveInvDir(InventoryFolderImpl inventoryFolder, string path) + { + List inventories = inventoryFolder.RequestListOfFolderImpls(); + List items = inventoryFolder.RequestListOfItems(); + string newPath = path + inventoryFolder.Name + InventoryFolderImpl.PATH_DELIMITER; + archive.AddDir(newPath); + foreach (InventoryFolderImpl folder in inventories) + { + saveInvDir(folder, newPath); + } + foreach (InventoryItemBase item in items) + { + saveInvItem(item, newPath); + } + } + + public void execute(string firstName, string lastName, string invPath, string savePath) + { + m_savePath = savePath; + + UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName); + if (null == userProfile) + { + m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName); + return; + } + + CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID); + if (null == userInfo) + { + m_log.ErrorFormat("[CONSOLE]: Failed to find user info for {0} {1} {2}", firstName, lastName, userProfile.ID); + return; + } + + InventoryFolderImpl inventoryFolder = null; + InventoryItemBase inventoryItem = null; + + if (userInfo.HasReceivedInventory) + { + // Eliminate double slashes and any leading / on the path. This might be better done within InventoryFolderImpl + // itself (possibly at a small loss in efficiency). + string[] components + = invPath.Split(new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); + invPath = String.Empty; + foreach (string c in components) + { + invPath += c + InventoryFolderImpl.PATH_DELIMITER; + } + + // Annoyingly Split actually returns the original string if the input string consists only of delimiters + // Therefore if we still start with a / after the split, then we need the root folder + if (invPath.Length == 0) + { + inventoryFolder = userInfo.RootFolder; + } + else + { + invPath = invPath.Remove(invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); + inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath); + } + + // The path may point to an item instead + if (inventoryFolder == null) + { + inventoryItem = userInfo.RootFolder.FindItemByPath(invPath); + } + } + else + { + m_log.ErrorFormat("[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}", firstName, lastName, userProfile.ID); + return; + } + + if (null == inventoryFolder) + { + if (null == inventoryItem) + { + m_log.ErrorFormat("[CONSOLE]: Could not find inventory entry at path {0}", invPath); + return; + } + else + { + m_log.InfoFormat("[CONSOLE]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, + invPath); + //get and export item info + saveInvItem(inventoryItem, invPath); + } + } + else + { + m_log.InfoFormat("[CONSOLE]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID, + invPath); + //recurse through all dirs getting dirs and files + saveInvDir(inventoryFolder, ""); + } + + new AssetsRequest(assetUuids.Keys, scene.AssetCache, ReceivedAllAssets).Execute(); + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs new file mode 100644 index 0000000..d2cf6c9 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -0,0 +1,389 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer +{ + public class InventoryTransferModule : IInventoryTransferModule, IRegionModule + { + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + private List m_Scenelist = new List(); + private Dictionary m_AgentRegions = + new Dictionary(); + + private IMessageTransferModule m_TransferModule = null; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (config.Configs["Messaging"] != null) + { + // Allow disabling this module in config + // + if (config.Configs["Messaging"].GetString( + "InventoryTransferModule", "InventoryTransferModule") != + "InventoryTransferModule") + return; + } + + if (!m_Scenelist.Contains(scene)) + { + if (m_Scenelist.Count == 0) + { + m_TransferModule = scene.RequestModuleInterface(); + if (m_TransferModule == null) + m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only"); + } + + m_Scenelist.Add(scene); + + scene.RegisterModuleInterface(this); + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnClientClosed += ClientLoggedOut; + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "InventoryModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void OnNewClient(IClientAPI client) + { + // Inventory giving is conducted via instant message + client.OnInstantMessage += OnInstantMessage; + } + + private Scene FindClientScene(UUID agentId) + { + lock (m_Scenelist) + { + foreach (Scene scene in m_Scenelist) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null) + { + if (!presence.IsChildAgent) + return scene; + } + } + } + return null; + } + + private void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + Scene scene = FindClientScene(client.AgentId); + + if (scene == null) // Something seriously wrong here. + return; + + if (im.dialog == (byte) InstantMessageDialog.InventoryOffered) + { + //m_log.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); + + ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); + UUID copyID; + + // First byte is the asset type + AssetType assetType = (AssetType)im.binaryBucket[0]; + + if (AssetType.Folder == assetType) + { + UUID folderID = new UUID(im.binaryBucket, 1); + + m_log.DebugFormat("[AGENT INVENTORY]: Inserting original folder {0} "+ + "into agent {1}'s inventory", + folderID, new UUID(im.toAgentID)); + + InventoryFolderImpl folderCopy + = scene.GiveInventoryFolder(new UUID(im.toAgentID), client.AgentId, folderID, UUID.Zero); + + if (folderCopy == null) + { + client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); + return; + } + + // The outgoing binary bucket should contain only the byte which signals an asset folder is + // being copied and the following bytes for the copied folder's UUID + copyID = folderCopy.ID; + byte[] copyIDBytes = copyID.GetBytes(); + im.binaryBucket = new byte[1 + copyIDBytes.Length]; + im.binaryBucket[0] = (byte)AssetType.Folder; + Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length); + + if (user != null && !user.IsChildAgent) + { + user.ControllingClient.SendBulkUpdateInventory(folderCopy); + } + } + else + { + // First byte of the array is probably the item type + // Next 16 bytes are the UUID + + UUID itemID = new UUID(im.binaryBucket, 1); + + m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+ + "into agent {1}'s inventory", + itemID, new UUID(im.toAgentID)); + + InventoryItemBase itemCopy = scene.GiveInventoryItem( + new UUID(im.toAgentID), + client.AgentId, itemID); + + if (itemCopy == null) + { + client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); + return; + } + + copyID = itemCopy.ID; + Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16); + + if (user != null && !user.IsChildAgent) + { + user.ControllingClient.SendBulkUpdateInventory(itemCopy); + } + } + + // Send the IM to the recipient. The item is already + // in their inventory, so it will not be lost if + // they are offline. + // + if (user != null && !user.IsChildAgent) + { + // And notify. Transaction ID is the item ID. We get that + // same ID back on the reply so we know what to act on + // + user.ControllingClient.SendInstantMessage( + new UUID(im.fromAgentID), im.message, + new UUID(im.toAgentID), + im.fromAgentName, im.dialog, im.timestamp, + copyID, false, im.binaryBucket); + + return; + } + else + { + if (m_TransferModule != null) + m_TransferModule.SendInstantMessage(im, delegate(bool success) {} ); + } + } + else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) + { + ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); + + if (user != null) // Local + { + user.ControllingClient.SendInstantMessage( + new UUID(im.fromAgentID), im.message, + new UUID(im.toAgentID), + im.fromAgentName, im.dialog, im.timestamp, + UUID.Zero, false, im.binaryBucket); + } + else + { + if (m_TransferModule != null) + m_TransferModule.SendInstantMessage(im, delegate(bool success) {} ); + } + } + else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined) + { + // Here, the recipient is local and we can assume that the + // inventory is loaded. Courtesy of the above bulk update, + // It will have been pushed to the client, too + // + + CachedUserInfo userInfo = + scene.CommsManager.UserProfileCacheService. + GetUserDetails(client.AgentId); + + if (userInfo != null) + { + InventoryFolderImpl trashFolder = + userInfo.FindFolderForType((int)AssetType.TrashFolder); + + UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip + + InventoryItemBase item = userInfo.RootFolder.FindItem(inventoryEntityID); + InventoryFolderBase folder = null; + + if (item != null && trashFolder != null) + { + item.Folder = trashFolder.ID; + + userInfo.DeleteItem(inventoryEntityID); + + scene.AddInventoryItem(client, item); + } + else + { + folder = userInfo.RootFolder.FindFolder(inventoryEntityID); + + if (folder != null & trashFolder != null) + { + userInfo.MoveFolder(inventoryEntityID, trashFolder.ID); + } + } + + if ((null == item && null == folder) | null == trashFolder) + { + string reason = String.Empty; + + if (trashFolder == null) + reason += " Trash folder not found."; + if (item == null) + reason += " Item not found."; + if (folder == null) + reason += " Folder not found."; + + client.SendAgentAlertMessage("Unable to delete "+ + "received inventory" + reason, false); + } + } + + ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); + + if (user != null) // Local + { + user.ControllingClient.SendInstantMessage( + new UUID(im.fromAgentID), im.message, + new UUID(im.toAgentID), + im.fromAgentName, im.dialog, im.timestamp, + UUID.Zero, false, im.binaryBucket); + } + else + { + if (m_TransferModule != null) + m_TransferModule.SendInstantMessage(im, delegate(bool success) {} ); + } + } + } + + public void SetRootAgentScene(UUID agentID, Scene scene) + { + m_AgentRegions[agentID] = scene; + } + + public bool NeedSceneCacheClear(UUID agentID, Scene scene) + { + if (!m_AgentRegions.ContainsKey(agentID)) + { + // Since we can get here two ways, we need to scan + // the scenes here. This is somewhat more expensive + // but helps avoid a nasty bug + // + + foreach (Scene s in m_Scenelist) + { + ScenePresence presence; + + if (s.TryGetAvatar(agentID, out presence)) + { + // If the agent is in this scene, then we + // are being called twice in a single + // teleport. This is wasteful of cycles + // but harmless due to this 2nd level check + // + // If the agent is found in another scene + // then the list wasn't current + // + // If the agent is totally unknown, then what + // are we even doing here?? + // + if (s == scene) + { + //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); + return true; + } + else + { + //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); + return false; + } + } + } + //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); + return true; + } + + // The agent is left in current Scene, so we must be + // going to another instance + // + if (m_AgentRegions[agentID] == scene) + { + //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); + m_AgentRegions.Remove(agentID); + return true; + } + + // Another region has claimed the agent + // + //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); + return false; + } + + public void ClientLoggedOut(UUID agentID) + { + if (m_AgentRegions.ContainsKey(agentID)) + m_AgentRegions.Remove(agentID); + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs new file mode 100644 index 0000000..ebf4f0a --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -0,0 +1,176 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Net; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Lure +{ + public class LureModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private readonly List m_scenes = new List(); + + private IMessageTransferModule m_TransferModule = null; + + public void Initialise(Scene scene, IConfigSource config) + { + if (config.Configs["Messaging"] != null) + { + if (config.Configs["Messaging"].GetString( + "LureModule", "LureModule") != + "LureModule") + return; + } + + lock (m_scenes) + { + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnIncomingInstantMessage += + OnGridInstantMessage; + } + } + } + + void OnNewClient(IClientAPI client) + { + client.OnInstantMessage += OnInstantMessage; + client.OnStartLure += OnStartLure; + client.OnTeleportLureRequest += OnTeleportLureRequest; + } + + public void PostInitialise() + { + m_TransferModule = + m_scenes[0].RequestModuleInterface(); + + if (m_TransferModule == null) + m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+ + "lures will not work!"); + } + + public void Close() + { + } + + public string Name + { + get { return "LureModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + } + + public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + ScenePresence presence = scene.GetScenePresence(client.AgentId); + + UUID dest = Util.BuildFakeParcelID( + scene.RegionInfo.RegionHandle, + (uint)presence.AbsolutePosition.X, + (uint)presence.AbsolutePosition.Y, + (uint)presence.AbsolutePosition.Z); + + m_log.DebugFormat("TP invite with message {0}", message); + + GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, + client.FirstName+" "+client.LastName, targetid, + (byte)InstantMessageDialog.RequestTeleport, false, + message, dest, false, presence.AbsolutePosition, + new Byte[0]); + + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(m, + delegate(bool success) { }); + } + } + + public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + + ulong handle = 0; + uint x = 128; + uint y = 128; + uint z = 70; + + Util.ParseFakeParcelID(lureID, out handle, out x, out y, out z); + + Vector3 position = new Vector3(); + position.X = (float)x; + position.Y = (float)y; + position.Z = (float)z; + + scene.RequestTeleportLocation(client, handle, position, + Vector3.Zero, teleportFlags); + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Forward remote teleport requests + // + if (msg.dialog != 22) + return; + + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(msg, + delegate(bool success) { }); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs new file mode 100644 index 0000000..193307d --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs @@ -0,0 +1,368 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Caps = OpenSim.Framework.Communications.Capabilities.Caps; + +namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps +{ + public class ObjectAdd : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + #region IRegionModule Members + + public void Initialise(Scene pScene, IConfigSource pSource) + { + m_scene = pScene; + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void PostInitialise() + { + + } + + public void RegisterCaps(UUID agentID, Caps caps) + { + UUID capuuid = UUID.Random(); + + m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/"); + + caps.RegisterHandler("ObjectAdd", + new RestHTTPHandler("POST", "/CAPS/OA/" + capuuid + "/", + delegate(Hashtable m_dhttpMethod) + { + return ProcessAdd(m_dhttpMethod, agentID, caps); + })); + } + + public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap) + { + Hashtable responsedata = new Hashtable(); + responsedata["int_response_code"] = 400; //501; //410; //404; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = "Request wasn't what was expected"; + ScenePresence avatar; + + if (!m_scene.TryGetAvatar(AgentId, out avatar)) + return responsedata; + + + OSD r = OSDParser.DeserializeLLSDXml((string)request["requestbody"]); + //UUID session_id = UUID.Zero; + bool bypass_raycast = false; + uint everyone_mask = 0; + uint group_mask = 0; + uint next_owner_mask = 0; + uint flags = 0; + UUID group_id = UUID.Zero; + int hollow = 0; + int material = 0; + int p_code = 0; + int path_begin = 0; + int path_curve = 0; + int path_end = 0; + int path_radius_offset = 0; + int path_revolutions = 0; + int path_scale_x = 0; + int path_scale_y = 0; + int path_shear_x = 0; + int path_shear_y = 0; + int path_skew = 0; + int path_taper_x = 0; + int path_taper_y = 0; + int path_twist = 0; + int path_twist_begin = 0; + int profile_begin = 0; + int profile_curve = 0; + int profile_end = 0; + Vector3 ray_end = Vector3.Zero; + bool ray_end_is_intersection = false; + Vector3 ray_start = Vector3.Zero; + UUID ray_target_id = UUID.Zero; + Quaternion rotation = Quaternion.Identity; + Vector3 scale = Vector3.Zero; + int state = 0; + + if (r.Type != OSDType.Map) // not a proper req + return responsedata; + + OSDMap rm = (OSDMap)r; + + if (rm.ContainsKey("ObjectData")) //v2 + { + if (rm["ObjectData"].Type != OSDType.Map) + { + responsedata["str_response_string"] = "Has ObjectData key, but data not in expected format"; + return responsedata; + } + + OSDMap ObjMap = (OSDMap) rm["ObjectData"]; + + bypass_raycast = ObjMap["BypassRaycast"].AsBoolean(); + everyone_mask = readuintval(ObjMap["EveryoneMask"]); + flags = readuintval(ObjMap["Flags"]); + group_mask = readuintval(ObjMap["GroupMask"]); + material = ObjMap["Material"].AsInteger(); + next_owner_mask = readuintval(ObjMap["NextOwnerMask"]); + p_code = ObjMap["PCode"].AsInteger(); + + if (ObjMap.ContainsKey("Path")) + { + if (ObjMap["Path"].Type != OSDType.Map) + { + responsedata["str_response_string"] = "Has Path key, but data not in expected format"; + return responsedata; + } + + OSDMap PathMap = (OSDMap)ObjMap["Path"]; + path_begin = PathMap["Begin"].AsInteger(); + path_curve = PathMap["Curve"].AsInteger(); + path_end = PathMap["End"].AsInteger(); + path_radius_offset = PathMap["RadiusOffset"].AsInteger(); + path_revolutions = PathMap["Revolutions"].AsInteger(); + path_scale_x = PathMap["ScaleX"].AsInteger(); + path_scale_y = PathMap["ScaleY"].AsInteger(); + path_shear_x = PathMap["ShearX"].AsInteger(); + path_shear_y = PathMap["ShearY"].AsInteger(); + path_skew = PathMap["Skew"].AsInteger(); + path_taper_x = PathMap["TaperX"].AsInteger(); + path_taper_y = PathMap["TaperY"].AsInteger(); + path_twist = PathMap["Twist"].AsInteger(); + path_twist_begin = PathMap["TwistBegin"].AsInteger(); + + } + + if (ObjMap.ContainsKey("Profile")) + { + if (ObjMap["Profile"].Type != OSDType.Map) + { + responsedata["str_response_string"] = "Has Profile key, but data not in expected format"; + return responsedata; + } + + OSDMap ProfileMap = (OSDMap)ObjMap["Profile"]; + + profile_begin = ProfileMap["Begin"].AsInteger(); + profile_curve = ProfileMap["Curve"].AsInteger(); + profile_end = ProfileMap["End"].AsInteger(); + hollow = ProfileMap["Hollow"].AsInteger(); + } + ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean(); + + ray_target_id = ObjMap["RayTargetId"].AsUUID(); + state = ObjMap["State"].AsInteger(); + try + { + ray_end = ((OSDArray) ObjMap["RayEnd"]).AsVector3(); + ray_start = ((OSDArray) ObjMap["RayStart"]).AsVector3(); + scale = ((OSDArray) ObjMap["Scale"]).AsVector3(); + rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion(); + } + catch (Exception) + { + responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format"; + return responsedata; + } + + if (rm.ContainsKey("AgentData")) + { + if (rm["AgentData"].Type != OSDType.Map) + { + responsedata["str_response_string"] = "Has AgentData key, but data not in expected format"; + return responsedata; + } + + OSDMap AgentDataMap = (OSDMap) rm["AgentData"]; + + //session_id = AgentDataMap["SessionId"].AsUUID(); + group_id = AgentDataMap["GroupId"].AsUUID(); + } + + } + else + { //v1 + bypass_raycast = rm["bypass_raycast"].AsBoolean(); + + everyone_mask = readuintval(rm["everyone_mask"]); + flags = readuintval(rm["flags"]); + group_id = rm["group_id"].AsUUID(); + group_mask = readuintval(rm["group_mask"]); + hollow = rm["hollow"].AsInteger(); + material = rm["material"].AsInteger(); + next_owner_mask = readuintval(rm["next_owner_mask"]); + hollow = rm["hollow"].AsInteger(); + p_code = rm["p_code"].AsInteger(); + path_begin = rm["path_begin"].AsInteger(); + path_curve = rm["path_curve"].AsInteger(); + path_end = rm["path_end"].AsInteger(); + path_radius_offset = rm["path_radius_offset"].AsInteger(); + path_revolutions = rm["path_revolutions"].AsInteger(); + path_scale_x = rm["path_scale_x"].AsInteger(); + path_scale_y = rm["path_scale_y"].AsInteger(); + path_shear_x = rm["path_shear_x"].AsInteger(); + path_shear_y = rm["path_shear_y"].AsInteger(); + path_skew = rm["path_skew"].AsInteger(); + path_taper_x = rm["path_taper_x"].AsInteger(); + path_taper_y = rm["path_taper_y"].AsInteger(); + path_twist = rm["path_twist"].AsInteger(); + path_twist_begin = rm["path_twist_begin"].AsInteger(); + profile_begin = rm["profile_begin"].AsInteger(); + profile_curve = rm["profile_curve"].AsInteger(); + profile_end = rm["profile_end"].AsInteger(); + + ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean(); + + ray_target_id = rm["ray_target_id"].AsUUID(); + + + //session_id = rm["session_id"].AsUUID(); + state = rm["state"].AsInteger(); + try + { + ray_end = ((OSDArray)rm["ray_end"]).AsVector3(); + ray_start = ((OSDArray)rm["ray_start"]).AsVector3(); + rotation = ((OSDArray)rm["rotation"]).AsQuaternion(); + scale = ((OSDArray)rm["scale"]).AsVector3(); + } + catch (Exception) + { + responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format"; + return responsedata; + } + } + + + + Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false); + + PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); + + pbs.PathBegin = (ushort)path_begin; + pbs.PathCurve = (byte)path_curve; + pbs.PathEnd = (ushort)path_end; + pbs.PathRadiusOffset = (sbyte)path_radius_offset; + pbs.PathRevolutions = (byte)path_revolutions; + pbs.PathScaleX = (byte)path_scale_x; + pbs.PathScaleY = (byte)path_scale_y; + pbs.PathShearX = (byte) path_shear_x; + pbs.PathShearY = (byte)path_shear_y; + pbs.PathSkew = (sbyte)path_skew; + pbs.PathTaperX = (sbyte)path_taper_x; + pbs.PathTaperY = (sbyte)path_taper_y; + pbs.PathTwist = (sbyte)path_twist; + pbs.PathTwistBegin = (sbyte)path_twist_begin; + pbs.HollowShape = (HollowShape) hollow; + pbs.PCode = (byte)p_code; + pbs.ProfileBegin = (ushort) profile_begin; + pbs.ProfileCurve = (byte) profile_curve; + pbs.ProfileEnd = (ushort)profile_end; + pbs.Scale = scale; + pbs.State = (byte)state; + + SceneObjectGroup obj = null; ; + + if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos)) + { + // rez ON the ground, not IN the ground + pos.Z += 0.25F; + + obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs); + } + + + if (obj == null) + return responsedata; + + SceneObjectPart rootpart = obj.RootPart; + rootpart.Shape = pbs; + rootpart.Flags |= (PrimFlags)flags; + rootpart.EveryoneMask = everyone_mask; + rootpart.GroupID = group_id; + rootpart.GroupMask = group_mask; + rootpart.NextOwnerMask = next_owner_mask; + rootpart.Material = (byte)material; + + + + m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor); + + responsedata["int_response_code"] = 200; //501; //410; //404; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = String.Format("local_id{0}",ConvertUintToBytes(obj.LocalId)); + + return responsedata; + } + + private uint readuintval(OSD obj) + { + byte[] tmp = obj.AsBinary(); + if (BitConverter.IsLittleEndian) + Array.Reverse(tmp); + return Utils.BytesToUInt(tmp); + + } + private string ConvertUintToBytes(uint val) + { + byte[] resultbytes = Utils.UIntToBytes(val); + if (BitConverter.IsLittleEndian) + Array.Reverse(resultbytes); + return String.Format("{0}",Convert.ToBase64String(resultbytes)); + } + + public void Close() + { + + } + + public string Name + { + get { return "ObjectAddModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs b/OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs new file mode 100644 index 0000000..6ea5b56 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs @@ -0,0 +1,145 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Globalization; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Profiles +{ + public class AvatarProfilesModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + + public AvatarProfilesModule() + { + } + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "AvatarProfilesModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + public void NewClient(IClientAPI client) + { + client.OnRequestAvatarProperties += RequestAvatarProperty; + client.OnUpdateAvatarProperties += UpdateAvatarProperties; + } + + public void RemoveClient(IClientAPI client) + { + client.OnRequestAvatarProperties -= RequestAvatarProperty; + client.OnUpdateAvatarProperties -= UpdateAvatarProperties; + } + + /// + /// + /// + /// + /// + public void RequestAvatarProperty(IClientAPI remoteClient, UUID avatarID) + { + // FIXME: finish adding fields such as url, masking, etc. + UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID); + if (null != profile) + { + Byte[] charterMember; + if (profile.CustomType == "") + { + charterMember = new Byte[1]; + charterMember[0] = (Byte)((profile.UserFlags & 0xf00) >> 8); + } + else + { + charterMember = Utils.StringToBytes(profile.CustomType); + } + + remoteClient.SendAvatarProperties(profile.ID, profile.AboutText, + Util.ToDateTime(profile.Created).ToString("M/d/yyyy", CultureInfo.InvariantCulture), + charterMember, profile.FirstLifeAboutText, (uint)(profile.UserFlags & 0xff), + profile.FirstLifeImage, profile.Image, String.Empty, profile.Partner); + } + else + { + m_log.Debug("[AvatarProfilesModule]: Got null for profile for " + avatarID.ToString()); + } + } + + public void UpdateAvatarProperties(IClientAPI remoteClient, UserProfileData newProfile) + { + UserProfileData Profile = m_scene.CommsManager.UserService.GetUserProfile(newProfile.ID); + + // if it's the profile of the user requesting the update, then we change only a few things. + if (remoteClient.AgentId.CompareTo(Profile.ID) == 0) + { + Profile.Image = newProfile.Image; + Profile.FirstLifeImage = newProfile.FirstLifeImage; + Profile.AboutText = newProfile.AboutText; + Profile.FirstLifeAboutText = newProfile.FirstLifeAboutText; + } + else + { + return; + } + + if (m_scene.CommsManager.UserService.UpdateUserProfile(Profile)) + { + RequestAvatarProperty(remoteClient, newProfile.ID); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs b/OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs new file mode 100644 index 0000000..3a9df4a --- /dev/null +++ b/OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs @@ -0,0 +1,244 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Threading; +using System.Xml; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Communications.Local +{ + public class LocalInterregionComms : IRegionModule, IInterregionCommsOut, IInterregionCommsIn + { + private bool m_enabled = false; + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private List m_sceneList = new List(); + + #region Events + public event ChildAgentUpdateReceived OnChildAgentUpdate; + + #endregion /* Events */ + + #region IRegionModule + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_sceneList.Count == 0) + { + IConfig startupConfig = config.Configs["Communications"]; + + if ((startupConfig != null) && (startupConfig.GetString("InterregionComms", "RESTCommms") == "LocalComms")) + { + m_log.Debug("[LOCAL COMMS]: Enabling InterregionComms LocalComms module"); + m_enabled = true; + } + } + + if (!m_enabled) + return; + + Init(scene); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "LocalInterregionCommsModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + /// + /// Can be called from other modules. + /// + /// + public void Init(Scene scene) + { + if (!m_sceneList.Contains(scene)) + { + lock (m_sceneList) + { + m_sceneList.Add(scene); + if (m_enabled) + scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); + } + + } + } + + #endregion /* IRegionModule */ + + #region IInterregionComms + + /** + * Agent-related communications + */ + + public bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit) + { + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { +// m_log.DebugFormat("[LOCAL COMMS]: Found region {0} to send SendCreateChildAgent", regionHandle); + s.NewUserConnection(aCircuit); + return true; + } + } + +// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for SendCreateChildAgent", regionHandle); + return false; + } + + public bool SendChildAgentUpdate(ulong regionHandle, AgentData cAgentData) + { + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.DebugFormat( + // "[LOCAL COMMS]: Found region {0} {1} to send ChildAgentUpdate", + // s.RegionInfo.RegionName, regionHandle); + + s.IncomingChildAgentDataUpdate(cAgentData); + return true; + } + } + +// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle); + return false; + } + + public bool SendChildAgentUpdate(ulong regionHandle, AgentPosition cAgentData) + { + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); + s.IncomingChildAgentDataUpdate(cAgentData); + return true; + } + } + //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); + return false; + } + + public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri) + { + //uint x, y; + //Utils.LongToUInts(regionHandle, out x, out y); + //x = x / Constants.RegionSize; + //y = y / Constants.RegionSize; + //Console.WriteLine("\n >>> Local SendReleaseAgent " + x + "-" + y); + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to SendReleaseAgent"); + return s.IncomingReleaseAgent(id); + } + } + //m_log.Debug("[LOCAL COMMS]: region not found in SendReleaseAgent"); + return false; + } + + public bool SendCloseAgent(ulong regionHandle, UUID id) + { + //uint x, y; + //Utils.LongToUInts(regionHandle, out x, out y); + //x = x / Constants.RegionSize; + //y = y / Constants.RegionSize; + //Console.WriteLine("\n >>> Local SendCloseAgent " + x + "-" + y); + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent"); + return s.IncomingCloseAgent(id); + } + } + //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); + return false; + } + + /** + * Object-related communications + */ + + public bool SendCreateObject(ulong regionHandle, ISceneObject sog) + { + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); + return s.IncomingCreateObject(sog); + } + } + return false; + } + + #endregion /* IInterregionComms */ + + #region Misc + + public UUID GetRegionID(ulong regionhandle) + { + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionhandle) + return s.RegionInfo.RegionID; + } + // ? weird. should not happen + return m_sceneList[0].RegionInfo.RegionID; + } + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs b/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs new file mode 100644 index 0000000..b4f4814 --- /dev/null +++ b/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs @@ -0,0 +1,960 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Threading; +using System.Xml; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Hypergrid; +using OpenSim.Region.CoreModules.Communications.Local; + +namespace OpenSim.Region.CoreModules.Communications.REST +{ + public class RESTInterregionComms : IRegionModule, IInterregionCommsOut + { + private static bool initialized = false; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected bool m_enabled = false; + protected Scene m_aScene; + // RESTInterregionComms does not care about local regions; it delegates that to the Local module + protected LocalInterregionComms m_localBackend; + + protected CommunicationsManager m_commsManager; + + #region IRegionModule + + public virtual void Initialise(Scene scene, IConfigSource config) + { + if (!initialized) + { + initialized = true; + IConfig startupConfig = config.Configs["Communications"]; + + if ((startupConfig == null) + || (startupConfig != null) + && (startupConfig.GetString("InterregionComms", "RESTComms") == "RESTComms")) + { + m_log.Info("[REST COMMS]: Enabling InterregionComms RESTComms module"); + m_enabled = true; + InitOnce(scene); + } + } + + if (!m_enabled) + return; + + InitEach(scene); + + } + + public virtual void PostInitialise() + { + if (m_enabled) + AddHTTPHandlers(); + } + + public virtual void Close() + { + } + + public virtual string Name + { + get { return "RESTInterregionCommsModule"; } + } + + public virtual bool IsSharedModule + { + get { return true; } + } + + protected virtual void InitEach(Scene scene) + { + m_localBackend.Init(scene); + scene.RegisterModuleInterface(this); + } + + protected virtual void InitOnce(Scene scene) + { + m_localBackend = new LocalInterregionComms(); + m_commsManager = scene.CommsManager; + m_aScene = scene; + } + + protected virtual void AddHTTPHandlers() + { + m_aScene.CommsManager.HttpServer.AddHTTPHandler("/agent/", AgentHandler); + m_aScene.CommsManager.HttpServer.AddHTTPHandler("/object/", ObjectHandler); + } + + #endregion /* IRegionModule */ + + #region IInterregionComms + + /** + * Agent-related communications + */ + + public bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit) + { + // Try local first + if (m_localBackend.SendCreateChildAgent(regionHandle, aCircuit)) + return true; + + // else do the remote thing + RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + SendUserInformation(regInfo, aCircuit); + + return DoCreateChildAgentCall(regInfo, aCircuit); + } + //else + // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); + return false; + } + + public bool SendChildAgentUpdate(ulong regionHandle, AgentData cAgentData) + { + // Try local first + if (m_localBackend.SendChildAgentUpdate(regionHandle, cAgentData)) + return true; + + // else do the remote thing + RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + return DoChildAgentUpdateCall(regInfo, cAgentData); + } + //else + // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); + return false; + + } + + public bool SendChildAgentUpdate(ulong regionHandle, AgentPosition cAgentData) + { + // Try local first + if (m_localBackend.SendChildAgentUpdate(regionHandle, cAgentData)) + return true; + + // else do the remote thing + RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + return DoChildAgentUpdateCall(regInfo, cAgentData); + } + //else + // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); + return false; + + } + + public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri) + { + // Try local first + if (m_localBackend.SendReleaseAgent(regionHandle, id, uri)) + return true; + + // else do the remote thing + return DoReleaseAgentCall(regionHandle, id, uri); + } + + public bool SendCloseAgent(ulong regionHandle, UUID id) + { + // Try local first + if (m_localBackend.SendCloseAgent(regionHandle, id)) + return true; + + // else do the remote thing + RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + return DoCloseAgentCall(regInfo, id); + } + //else + // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); + return false; + } + + /** + * Object-related communications + */ + + public bool SendCreateObject(ulong regionHandle, ISceneObject sog) + { + // Try local first + ISceneObject sogClone = sog.CloneForNewScene(); + if (m_localBackend.SendCreateObject(regionHandle, sogClone)) + { + //m_log.Debug("[REST COMMS]: LocalBackEnd SendCreateObject succeeded"); + return true; + } + + // else do the remote thing + RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + return DoCreateObjectCall(regInfo, sog); + } + //else + // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); + return false; + } + + #endregion /* IInterregionComms */ + + #region DoWork functions for the above public interface + + //------------------------------------------------------------------- + // Internal functions for the above public interface + //------------------------------------------------------------------- + + protected bool DoCreateChildAgentCall(RegionInfo region, AgentCircuitData aCircuit) + { + // Eventually, we want to use a caps url instead of the agentID + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + aCircuit.AgentID + "/"; + //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); + + WebRequest AgentCreateRequest = WebRequest.Create(uri); + AgentCreateRequest.Method = "POST"; + AgentCreateRequest.ContentType = "application/json"; + AgentCreateRequest.Timeout = 10000; + + // Fill it in + OSDMap args = null; + try + { + args = aCircuit.PackAgentCircuitData(); + } + catch (Exception e) + { + m_log.Debug("[REST COMMS]: PackAgentCircuitData failed with exception: " + e.Message); + } + // Add the regionhandle of the destination region + ulong regionHandle = GetRegionHandle(region.RegionHandle); + args["destination_handle"] = OSD.FromString(regionHandle.ToString()); + + string strBuffer = ""; + byte[] buffer = new byte[1]; + try + { + strBuffer = OSDParser.SerializeJsonString(args); + System.Text.UTF8Encoding str = new System.Text.UTF8Encoding(); + buffer = str.GetBytes(strBuffer); + + } + catch (Exception e) + { + m_log.WarnFormat("[OSG2]: Exception thrown on serialization of ChildCreate: {0}", e.Message); + // ignore. buffer will be empty, caller should check. + } + + Stream os = null; + try + { // send the Post + AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send + os = AgentCreateRequest.GetRequestStream(); + os.Write(buffer, 0, strBuffer.Length); //Send it + os.Close(); + //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri); + } + //catch (WebException ex) + catch + { + //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message); + + return false; + } + + // Let's wait for the response + //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); + + try + { + WebResponse webResponse = AgentCreateRequest.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on DoCreateChildAgentCall post"); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); + // ignore, really + } + + return true; + + } + + protected bool DoChildAgentUpdateCall(RegionInfo region, IAgentData cAgentData) + { + // Eventually, we want to use a caps url instead of the agentID + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + cAgentData.AgentID + "/"; + //Console.WriteLine(" >>> DoChildAgentUpdateCall <<< " + uri); + + WebRequest ChildUpdateRequest = WebRequest.Create(uri); + ChildUpdateRequest.Method = "PUT"; + ChildUpdateRequest.ContentType = "application/json"; + ChildUpdateRequest.Timeout = 10000; + + // Fill it in + OSDMap args = null; + try + { + args = cAgentData.PackUpdateMessage(); + } + catch (Exception e) + { + m_log.Debug("[REST COMMS]: PackUpdateMessage failed with exception: " + e.Message); + } + // Add the regionhandle of the destination region + ulong regionHandle = GetRegionHandle(region.RegionHandle); + args["destination_handle"] = OSD.FromString(regionHandle.ToString()); + + string strBuffer = ""; + byte[] buffer = new byte[1]; + try + { + strBuffer = OSDParser.SerializeJsonString(args); + System.Text.UTF8Encoding str = new System.Text.UTF8Encoding(); + buffer = str.GetBytes(strBuffer); + + } + catch (Exception e) + { + m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildUpdate: {0}", e.Message); + // ignore. buffer will be empty, caller should check. + } + + Stream os = null; + try + { // send the Post + ChildUpdateRequest.ContentLength = buffer.Length; //Count bytes to send + os = ChildUpdateRequest.GetRequestStream(); + os.Write(buffer, 0, strBuffer.Length); //Send it + os.Close(); + //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri); + } + //catch (WebException ex) + catch + { + //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message); + + return false; + } + + // Let's wait for the response + //m_log.Info("[REST COMMS]: Waiting for a reply after ChildAgentUpdate"); + + try + { + WebResponse webResponse = ChildUpdateRequest.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on ChilAgentUpdate post"); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of ChilAgentUpdate {0}", ex.Message); + // ignore, really + } + + return true; + } + + protected bool DoReleaseAgentCall(ulong regionHandle, UUID id, string uri) + { + //Console.WriteLine(" >>> DoReleaseAgentCall <<< " + uri); + + WebRequest request = WebRequest.Create(uri); + request.Method = "DELETE"; + request.Timeout = 10000; + + try + { + WebResponse webResponse = request.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on agent get "); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message); + // ignore, really + } + + return true; + } + + protected bool DoCloseAgentCall(RegionInfo region, UUID id) + { + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() +"/"; + + //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); + + WebRequest request = WebRequest.Create(uri); + request.Method = "DELETE"; + request.Timeout = 10000; + + try + { + WebResponse webResponse = request.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on agent get "); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message); + // ignore, really + } + + return true; + } + + protected bool DoCreateObjectCall(RegionInfo region, ISceneObject sog) + { + ulong regionHandle = GetRegionHandle(region.RegionHandle); + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/object/" + sog.UUID + "/" + regionHandle.ToString() + "/"; + //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); + + WebRequest ObjectCreateRequest = WebRequest.Create(uri); + ObjectCreateRequest.Method = "POST"; + ObjectCreateRequest.ContentType = "text/xml"; + ObjectCreateRequest.Timeout = 10000; + + OSDMap args = new OSDMap(2); + args["sog"] = OSD.FromString(sog.ToXmlString2()); + args["extra"] = OSD.FromString(sog.ExtraToXmlString()); + if (m_aScene.m_allowScriptCrossings) + { + string state = sog.GetStateSnapshot(); + if (state.Length > 0) + args["state"] = OSD.FromString(state); + } + + string strBuffer = ""; + byte[] buffer = new byte[1]; + try + { + strBuffer = OSDParser.SerializeJsonString(args); + System.Text.UTF8Encoding str = new System.Text.UTF8Encoding(); + buffer = str.GetBytes(strBuffer); + + } + catch (Exception e) + { + m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of CreateObject: {0}", e.Message); + // ignore. buffer will be empty, caller should check. + } + + Stream os = null; + try + { // send the Post + ObjectCreateRequest.ContentLength = buffer.Length; //Count bytes to send + os = ObjectCreateRequest.GetRequestStream(); + os.Write(buffer, 0, strBuffer.Length); //Send it + os.Close(); + m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri); + } + //catch (WebException ex) + catch + { + // m_log.InfoFormat("[REST COMMS]: Bad send on CreateObject {0}", ex.Message); + + return false; + } + + // Let's wait for the response + //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); + + try + { + WebResponse webResponse = ObjectCreateRequest.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post"); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message); + // ignore, really + } + + return true; + + } + + #endregion /* Do Work */ + + #region Incoming calls from remote instances + + /** + * Agent-related incoming calls + */ + + public Hashtable AgentHandler(Hashtable request) + { + //m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called"); + + //Console.WriteLine("---------------------------"); + //Console.WriteLine(" >> uri=" + request["uri"]); + //Console.WriteLine(" >> content-type=" + request["content-type"]); + //Console.WriteLine(" >> http-method=" + request["http-method"]); + //Console.WriteLine("---------------------------\n"); + + Hashtable responsedata = new Hashtable(); + responsedata["content_type"] = "text/html"; + + UUID agentID; + string action; + ulong regionHandle; + if (!GetParams((string)request["uri"], out agentID, out regionHandle, out action)) + { + m_log.InfoFormat("[REST COMMS]: Invalid parameters for agent message {0}", request["uri"]); + responsedata["int_response_code"] = 404; + responsedata["str_response_string"] = "false"; + + return responsedata; + } + + // Next, let's parse the verb + string method = (string)request["http-method"]; + if (method.Equals("PUT")) + { + DoAgentPut(request, responsedata); + return responsedata; + } + else if (method.Equals("POST")) + { + DoAgentPost(request, responsedata, agentID); + return responsedata; + } + else if (method.Equals("DELETE")) + { + DoAgentDelete(request, responsedata, agentID, action, regionHandle); + + return responsedata; + } + else + { + m_log.InfoFormat("[REST COMMS]: method {0} not supported in agent message", method); + responsedata["int_response_code"] = 404; + responsedata["str_response_string"] = "false"; + + return responsedata; + } + + } + + protected OSDMap GetOSDMap(Hashtable request) + { + OSDMap args = null; + try + { + OSD buffer; + // We should pay attention to the content-type, but let's assume we know it's Json + buffer = OSDParser.DeserializeJson((string)request["body"]); + if (buffer.Type == OSDType.Map) + { + args = (OSDMap)buffer; + return args; + } + else + { + // uh? + m_log.Debug("[REST COMMS]: Got OSD of type " + buffer.Type.ToString()); + return null; + } + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on parse of REST message {0}", ex.Message); + return null; + } + } + + protected virtual void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) + { + OSDMap args = GetOSDMap(request); + if (args == null) + { + responsedata["int_response_code"] = 400; + responsedata["str_response_string"] = "false"; + return; + } + + // retrieve the regionhandle + ulong regionhandle = 0; + if (args["destination_handle"] != null) + UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle); + + AgentCircuitData aCircuit = new AgentCircuitData(); + try + { + aCircuit.UnpackAgentCircuitData(args); + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildCreate message {0}", ex.Message); + return; + } + + // This is the meaning of POST agent + AdjustUserInformation(aCircuit); + bool result = m_localBackend.SendCreateChildAgent(regionhandle, aCircuit); + + responsedata["int_response_code"] = 200; + responsedata["str_response_string"] = result.ToString(); + } + + protected virtual void DoAgentPut(Hashtable request, Hashtable responsedata) + { + OSDMap args = GetOSDMap(request); + if (args == null) + { + responsedata["int_response_code"] = 400; + responsedata["str_response_string"] = "false"; + return; + } + + // retrieve the regionhandle + ulong regionhandle = 0; + if (args["destination_handle"] != null) + UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle); + + string messageType; + if (args["message_type"] != null) + messageType = args["message_type"].AsString(); + else + { + m_log.Warn("[REST COMMS]: Agent Put Message Type not found. "); + messageType = "AgentData"; + } + + bool result = true; + if ("AgentData".Equals(messageType)) + { + AgentData agent = new AgentData(); + try + { + agent.UnpackUpdateMessage(args); + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildAgentUpdate message {0}", ex.Message); + return; + } + //agent.Dump(); + // This is one of the meanings of PUT agent + result = m_localBackend.SendChildAgentUpdate(regionhandle, agent); + + } + else if ("AgentPosition".Equals(messageType)) + { + AgentPosition agent = new AgentPosition(); + try + { + agent.UnpackUpdateMessage(args); + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildAgentUpdate message {0}", ex.Message); + return; + } + //agent.Dump(); + // This is one of the meanings of PUT agent + result = m_localBackend.SendChildAgentUpdate(regionhandle, agent); + + } + + + + responsedata["int_response_code"] = 200; + responsedata["str_response_string"] = result.ToString(); + } + + protected virtual void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, ulong regionHandle) + { + //Console.WriteLine(" >>> DoDelete action:" + action + "; regionHandle:" + regionHandle); + + if (action.Equals("release")) + m_localBackend.SendReleaseAgent(regionHandle, id, ""); + else + m_localBackend.SendCloseAgent(regionHandle, id); + + responsedata["int_response_code"] = 200; + responsedata["str_response_string"] = "OpenSim agent " + id.ToString(); + } + + /** + * Object-related incoming calls + */ + + public Hashtable ObjectHandler(Hashtable request) + { + //m_log.Debug("[CONNECTION DEBUGGING]: ObjectHandler Called"); + + //Console.WriteLine("---------------------------"); + //Console.WriteLine(" >> uri=" + request["uri"]); + //Console.WriteLine(" >> content-type=" + request["content-type"]); + //Console.WriteLine(" >> http-method=" + request["http-method"]); + //Console.WriteLine("---------------------------\n"); + + Hashtable responsedata = new Hashtable(); + responsedata["content_type"] = "text/html"; + + UUID objectID; + string action; + ulong regionHandle; + if (!GetParams((string)request["uri"], out objectID, out regionHandle, out action)) + { + m_log.InfoFormat("[REST COMMS]: Invalid parameters for object message {0}", request["uri"]); + responsedata["int_response_code"] = 404; + responsedata["str_response_string"] = "false"; + + return responsedata; + } + + // Next, let's parse the verb + string method = (string)request["http-method"]; + if (method.Equals("POST")) + { + DoObjectPost(request, responsedata, regionHandle); + return responsedata; + } + //else if (method.Equals("PUT")) + //{ + // DoObjectPut(request, responsedata, agentID); + // return responsedata; + //} + //else if (method.Equals("DELETE")) + //{ + // DoObjectDelete(request, responsedata, agentID, action, regionHandle); + // return responsedata; + //} + else + { + m_log.InfoFormat("[REST COMMS]: method {0} not supported in object message", method); + responsedata["int_response_code"] = 404; + responsedata["str_response_string"] = "false"; + + return responsedata; + } + + } + + protected virtual void DoObjectPost(Hashtable request, Hashtable responsedata, ulong regionhandle) + { + OSDMap args = GetOSDMap(request); + if (args == null) + { + responsedata["int_response_code"] = 400; + responsedata["str_response_string"] = "false"; + return; + } + + string sogXmlStr = "", extraStr = "", stateXmlStr = ""; + if (args["sog"] != null) + sogXmlStr = args["sog"].AsString(); + if (args["extra"] != null) + extraStr = args["extra"].AsString(); + + UUID regionID = m_localBackend.GetRegionID(regionhandle); + SceneObjectGroup sog = null; + try + { + sog = new SceneObjectGroup(sogXmlStr); + sog.ExtraFromXmlString(extraStr); + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on deserializing scene object {0}", ex.Message); + responsedata["int_response_code"] = 400; + responsedata["str_response_string"] = "false"; + return; + } + + if ((args["state"] != null) && m_aScene.m_allowScriptCrossings) + { + stateXmlStr = args["state"].AsString(); + if (stateXmlStr != "") + { + try + { + sog.SetState(stateXmlStr, regionID); + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on setting state for scene object {0}", ex.Message); + + } + } + } + // This is the meaning of POST object + bool result = m_localBackend.SendCreateObject(regionhandle, sog); + + responsedata["int_response_code"] = 200; + responsedata["str_response_string"] = result.ToString(); + } + + #endregion + + #region Misc + + /// + /// Extract the param from an uri. + /// + /// Something like this: /agent/uuid/ or /agent/uuid/handle/release + /// uuid on uuid field + /// optional action + protected bool GetParams(string uri, out UUID uuid, out ulong regionHandle, out string action) + { + uuid = UUID.Zero; + action = ""; + regionHandle = 0; + + uri = uri.Trim(new char[] { '/' }); + string[] parts = uri.Split('/'); + if (parts.Length <= 1) + { + return false; + } + else + { + if (!UUID.TryParse(parts[1], out uuid)) + return false; + + if (parts.Length >= 3) + UInt64.TryParse(parts[2], out regionHandle); + if (parts.Length >= 4) + action = parts[3]; + + return true; + } + } + + #endregion Misc + + #region Hyperlinks + + protected virtual ulong GetRegionHandle(ulong handle) + { + if (m_aScene.SceneGridService is HGSceneCommunicationService) + return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.FindRegionHandle(handle); + + return handle; + } + + protected virtual bool IsHyperlink(ulong handle) + { + if (m_aScene.SceneGridService is HGSceneCommunicationService) + return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.IsHyperlinkRegion(handle); + + return false; + } + + protected virtual void SendUserInformation(RegionInfo regInfo, AgentCircuitData aCircuit) + { + try + { + //if (IsHyperlink(regInfo.RegionHandle)) + if (m_aScene.SceneGridService is HGSceneCommunicationService) + { + ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.SendUserInformation(regInfo, aCircuit); + } + } + catch // Bad cast + { } + + } + + protected virtual void AdjustUserInformation(AgentCircuitData aCircuit) + { + if (m_aScene.SceneGridService is HGSceneCommunicationService) + ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.AdjustUserInformation(aCircuit); + } + #endregion /* Hyperlinks */ + + } +} diff --git a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs new file mode 100644 index 0000000..e81466a --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs @@ -0,0 +1,630 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Threading; +using System.Xml; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenMetaverse.StructuredData; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +using OSD = OpenMetaverse.StructuredData.OSD; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; +using Caps = OpenSim.Framework.Communications.Capabilities.Caps; +using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue; + +namespace OpenSim.Region.CoreModules.Framework.EventQueue +{ + public struct QueueItem + { + public int id; + public OSDMap body; + } + + public class EventQueueGetModule : IEventQueue, IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene = null; + private IConfigSource m_gConfig; + bool enabledYN = false; + + private Dictionary m_ids = new Dictionary(); + + private Dictionary queues = new Dictionary(); + private Dictionary m_QueueUUIDAvatarMapping = new Dictionary(); + private Dictionary m_AvatarQueueUUIDMapping = new Dictionary(); + + #region IRegionModule methods + public void Initialise(Scene scene, IConfigSource config) + { + m_gConfig = config; + + IConfig startupConfig = m_gConfig.Configs["Startup"]; + + ReadConfigAndPopulate(scene, startupConfig, "Startup"); + + if (enabledYN) + { + m_scene = scene; + scene.RegisterModuleInterface(this); + + // Register fallback handler + // Why does EQG Fail on region crossings! + + //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); + + scene.EventManager.OnNewClient += OnNewClient; + + // TODO: Leaving these open, or closing them when we + // become a child is incorrect. It messes up TP in a big + // way. CAPS/EQ need to be active as long as the UDP + // circuit is there. + + scene.EventManager.OnClientClosed += ClientClosed; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; + scene.EventManager.OnRegisterCaps += OnRegisterCaps; + } + else + { + m_gConfig = null; + } + + } + + private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p) + { + enabledYN = startupConfig.GetBoolean("EventQueue", true); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "EventQueueGetModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + #endregion + + /// + /// Always returns a valid queue + /// + /// + /// + private BlockingLLSDQueue TryGetQueue(UUID agentId) + { + lock (queues) + { + if (!queues.ContainsKey(agentId)) + { + m_log.DebugFormat( + "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}", + agentId, m_scene.RegionInfo.RegionName); + + queues[agentId] = new BlockingLLSDQueue(); + } + + return queues[agentId]; + } + } + + /// + /// May return a null queue + /// + /// + /// + private BlockingLLSDQueue GetQueue(UUID agentId) + { + lock (queues) + { + if (queues.ContainsKey(agentId)) + { + return queues[agentId]; + } + else + return null; + } + } + + #region IEventQueue Members + + public bool Enqueue(OSD ev, UUID avatarID) + { + //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName); + try + { + BlockingLLSDQueue queue = GetQueue(avatarID); + if (queue != null) + queue.Enqueue(ev); + } + catch(NullReferenceException e) + { + m_log.Error("[EVENTQUEUE] Caught exception: " + e); + return false; + } + + return true; + } + + #endregion + + private void OnNewClient(IClientAPI client) + { + //client.OnLogout += ClientClosed; + } + +// private void ClientClosed(IClientAPI client) +// { +// ClientClosed(client.AgentId); +// } + + private void ClientClosed(UUID AgentID) + { + m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName); + + int count = 0; + while (queues.ContainsKey(AgentID) && queues[AgentID].Count() > 0 && count++ < 5) + { + Thread.Sleep(1000); + } + + lock (queues) + { + queues.Remove(AgentID); + } + List removeitems = new List(); + lock (m_AvatarQueueUUIDMapping) + { + foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys) + { + if (ky == AgentID) + { + removeitems.Add(ky); + } + } + + foreach (UUID ky in removeitems) + { + m_AvatarQueueUUIDMapping.Remove(ky); + m_scene.CommsManager.HttpServer.RemoveHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/"); + } + + } + UUID searchval = UUID.Zero; + + removeitems.Clear(); + + lock (m_QueueUUIDAvatarMapping) + { + foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys) + { + searchval = m_QueueUUIDAvatarMapping[ky]; + + if (searchval == AgentID) + { + removeitems.Add(ky); + } + } + + foreach (UUID ky in removeitems) + m_QueueUUIDAvatarMapping.Remove(ky); + + } + } + + private void MakeChildAgent(ScenePresence avatar) + { + //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName); + //lock (m_ids) + // { + //if (m_ids.ContainsKey(avatar.UUID)) + //{ + // close the event queue. + //m_ids[avatar.UUID] = -1; + //} + //} + } + + public void OnRegisterCaps(UUID agentID, Caps caps) + { + // Register an event queue for the client + + //m_log.DebugFormat( + // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", + // agentID, caps, m_scene.RegionInfo.RegionName); + + // Let's instantiate a Queue for this agent right now + TryGetQueue(agentID); + + string capsBase = "/CAPS/EQG/"; + UUID EventQueueGetUUID = UUID.Zero; + + lock (m_AvatarQueueUUIDMapping) + { + // Reuse open queues. The client does! + if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) + { + m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); + EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; + } + else + { + EventQueueGetUUID = UUID.Random(); + //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); + } + } + + lock (m_QueueUUIDAvatarMapping) + { + if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID)) + m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID); + } + + lock (m_AvatarQueueUUIDMapping) + { + if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID)) + m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID); + } + + // Register this as a caps handler + caps.RegisterHandler("EventQueueGet", + new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/", + delegate(Hashtable m_dhttpMethod) + { + return ProcessQueue(m_dhttpMethod, agentID, caps); + })); + + // This will persist this beyond the expiry of the caps handlers + m_scene.CommsManager.HttpServer.AddHTTPHandler( + capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePath2); + + Random rnd = new Random(System.Environment.TickCount); + lock (m_ids) + { + if (!m_ids.ContainsKey(agentID)) + m_ids.Add(agentID, rnd.Next(30000000)); + } + } + + public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps) + { + // TODO: this has to be redone to not busy-wait (and block the thread), + // TODO: as soon as we have a non-blocking way to handle HTTP-requests. + +// if (m_log.IsDebugEnabled) +// { +// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ "; +// foreach (object key in request.Keys) +// { +// debug += key.ToString() + "=" + request[key].ToString() + " "; +// } +// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name); +// } + + BlockingLLSDQueue queue = TryGetQueue(agentID); + OSD element = queue.Dequeue(15000); // 15s timeout + + Hashtable responsedata = new Hashtable(); + + int thisID = 0; + lock (m_ids) + thisID = m_ids[agentID]; + + if (element == null) + { + //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName); + if (thisID == -1) // close-request + { + m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName); + responsedata["int_response_code"] = 404; //501; //410; //404; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = "Closed EQG"; + return responsedata; + } + responsedata["int_response_code"] = 502; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = "Upstream error: "; + responsedata["error_status_text"] = "Upstream error:"; + responsedata["http_protocol_version"] = "HTTP/1.0"; + return responsedata; + } + + OSDArray array = new OSDArray(); + if (element == null) // didn't have an event in 15s + { + // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say! + array.Add(EventQueueHelper.KeepAliveEvent()); + m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); + } + else + { + array.Add(element); + while (queue.Count() > 0) + { + array.Add(queue.Dequeue(1)); + thisID++; + } + } + + OSDMap events = new OSDMap(); + events.Add("events", array); + + events.Add("id", new OSDInteger(thisID)); + lock (m_ids) + { + m_ids[agentID] = thisID + 1; + } + + responsedata["int_response_code"] = 200; + responsedata["content_type"] = "application/xml"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events); + //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]); + + return responsedata; + } + + public Hashtable EventQueuePath2(Hashtable request) + { + string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/",""); + // pull off the last "/" in the path. + Hashtable responsedata = new Hashtable(); + capuuid = capuuid.Substring(0, capuuid.Length - 1); + capuuid = capuuid.Replace("/CAPS/EQG/", ""); + UUID AvatarID = UUID.Zero; + UUID capUUID = UUID.Zero; + + // parse the path and search for the avatar with it registered + if (UUID.TryParse(capuuid, out capUUID)) + { + lock (m_QueueUUIDAvatarMapping) + { + if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) + { + AvatarID = m_QueueUUIDAvatarMapping[capUUID]; + } + } + if (AvatarID != UUID.Zero) + { + return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsHandlerForUser(AvatarID)); + } + else + { + responsedata["int_response_code"] = 404; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = "Not Found"; + responsedata["error_status_text"] = "Not Found"; + responsedata["http_protocol_version"] = "HTTP/1.0"; + return responsedata; + // return 404 + } + } + else + { + responsedata["int_response_code"] = 404; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = "Not Found"; + responsedata["error_status_text"] = "Not Found"; + responsedata["http_protocol_version"] = "HTTP/1.0"; + return responsedata; + // return 404 + } + + } + + public OSD EventQueueFallBack(string path, OSD request, string endpoint) + { + // This is a fallback element to keep the client from loosing EventQueueGet + // Why does CAPS fail sometimes!? + m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!"); + string capuuid = path.Replace("/CAPS/EQG/",""); + capuuid = capuuid.Substring(0, capuuid.Length - 1); + +// UUID AvatarID = UUID.Zero; + UUID capUUID = UUID.Zero; + if (UUID.TryParse(capuuid, out capUUID)) + { +/* Don't remove this yet code cleaners! + * Still testing this! + * + lock (m_QueueUUIDAvatarMapping) + { + if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) + { + AvatarID = m_QueueUUIDAvatarMapping[capUUID]; + } + } + + + if (AvatarID != UUID.Zero) + { + // Repair the CAP! + //OpenSim.Framework.Communications.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID); + //string capsBase = "/CAPS/EQG/"; + //caps.RegisterHandler("EventQueueGet", + //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/", + //delegate(Hashtable m_dhttpMethod) + //{ + // return ProcessQueue(m_dhttpMethod, AvatarID, caps); + //})); + // start new ID sequence. + Random rnd = new Random(System.Environment.TickCount); + lock (m_ids) + { + if (!m_ids.ContainsKey(AvatarID)) + m_ids.Add(AvatarID, rnd.Next(30000000)); + } + + + int thisID = 0; + lock (m_ids) + thisID = m_ids[AvatarID]; + + BlockingLLSDQueue queue = GetQueue(AvatarID); + OSDArray array = new OSDArray(); + LLSD element = queue.Dequeue(15000); // 15s timeout + if (element == null) + { + + array.Add(EventQueueHelper.KeepAliveEvent()); + } + else + { + array.Add(element); + while (queue.Count() > 0) + { + array.Add(queue.Dequeue(1)); + thisID++; + } + } + OSDMap events = new OSDMap(); + events.Add("events", array); + + events.Add("id", new LLSDInteger(thisID)); + + lock (m_ids) + { + m_ids[AvatarID] = thisID + 1; + } + + return events; + } + else + { + return new LLSD(); + } +* +*/ + } + else + { + //return new LLSD(); + } + + return new OSDString("shutdown404!"); + } + + public void DisableSimulator(ulong handle, UUID avatarID) + { + OSD item = EventQueueHelper.DisableSimulator(handle); + Enqueue(item, avatarID); + } + + public void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID) + { + OSD item = EventQueueHelper.EnableSimulator(handle, endPoint); + Enqueue(item, avatarID); + } + + public void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath) + { + OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath); + Enqueue(item, avatarID); + } + + public void TeleportFinishEvent(ulong regionHandle, byte simAccess, + IPEndPoint regionExternalEndPoint, + uint locationID, uint flags, string capsURL, + UUID avatarID) + { + OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint, + locationID, flags, capsURL, avatarID); + Enqueue(item, avatarID); + } + + public void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, + IPEndPoint newRegionExternalEndPoint, + string capsURL, UUID avatarID, UUID sessionID) + { + OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint, + capsURL, avatarID, sessionID); + Enqueue(item, avatarID); + } + + public void ChatterboxInvitation(UUID sessionID, string sessionName, + UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, + uint timeStamp, bool offline, int parentEstateID, Vector3 position, + uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) + { + OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog, + timeStamp, offline, parentEstateID, position, ttl, transactionID, + fromGroup, binaryBucket); + Enqueue(item, toAgent); + m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item); + + } + + public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, + bool isModerator, bool textMute) + { + OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat, + isModerator, textMute); + Enqueue(item, toAgent); + m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); + } + + public void ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket, UUID avatarID) + { + OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesPacket); + Enqueue(item, avatarID); + } + + public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID) + { + OSD item = EventQueueHelper.GroupMembership(groupUpdate); + Enqueue(item, avatarID); + } + } +} diff --git a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs new file mode 100644 index 0000000..80f6fce --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs @@ -0,0 +1,459 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Net; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Region.CoreModules.Framework.EventQueue +{ + public class EventQueueHelper + { + private EventQueueHelper() {} // no construction possible, it's an utility class + + private static byte[] ulongToByteArray(ulong uLongValue) + { + // Reverse endianness of RegionHandle + return new byte[] + { + (byte)((uLongValue >> 56) % 256), + (byte)((uLongValue >> 48) % 256), + (byte)((uLongValue >> 40) % 256), + (byte)((uLongValue >> 32) % 256), + (byte)((uLongValue >> 24) % 256), + (byte)((uLongValue >> 16) % 256), + (byte)((uLongValue >> 8) % 256), + (byte)(uLongValue % 256) + }; + } + + private static byte[] uintToByteArray(uint uIntValue) + { + byte[] resultbytes = Utils.UIntToBytes(uIntValue); + if (BitConverter.IsLittleEndian) + Array.Reverse(resultbytes); + + return resultbytes; + } + + public static OSD buildEvent(string eventName, OSD eventBody) + { + OSDMap llsdEvent = new OSDMap(2); + llsdEvent.Add("message", new OSDString(eventName)); + llsdEvent.Add("body", eventBody); + + return llsdEvent; + } + + public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint) + { + OSDMap llsdSimInfo = new OSDMap(3); + + llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle))); + llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes())); + llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port)); + + OSDArray arr = new OSDArray(1); + arr.Add(llsdSimInfo); + + OSDMap llsdBody = new OSDMap(1); + llsdBody.Add("SimulatorInfo", arr); + + return buildEvent("EnableSimulator", llsdBody); + } + + public static OSD DisableSimulator(ulong handle) + { + //OSDMap llsdSimInfo = new OSDMap(1); + + //llsdSimInfo.Add("Handle", new OSDBinary(regionHandleToByteArray(handle))); + + //OSDArray arr = new OSDArray(1); + //arr.Add(llsdSimInfo); + + OSDMap llsdBody = new OSDMap(0); + //llsdBody.Add("SimulatorInfo", arr); + + return buildEvent("DisableSimulator", llsdBody); + } + + public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, + IPEndPoint newRegionExternalEndPoint, + string capsURL, UUID agentID, UUID sessionID) + { + OSDArray lookAtArr = new OSDArray(3); + lookAtArr.Add(OSD.FromReal(lookAt.X)); + lookAtArr.Add(OSD.FromReal(lookAt.Y)); + lookAtArr.Add(OSD.FromReal(lookAt.Z)); + + OSDArray positionArr = new OSDArray(3); + positionArr.Add(OSD.FromReal(pos.X)); + positionArr.Add(OSD.FromReal(pos.Y)); + positionArr.Add(OSD.FromReal(pos.Z)); + + OSDMap infoMap = new OSDMap(2); + infoMap.Add("LookAt", lookAtArr); + infoMap.Add("Position", positionArr); + + OSDArray infoArr = new OSDArray(1); + infoArr.Add(infoMap); + + OSDMap agentDataMap = new OSDMap(2); + agentDataMap.Add("AgentID", OSD.FromUUID(agentID)); + agentDataMap.Add("SessionID", OSD.FromUUID(sessionID)); + + OSDArray agentDataArr = new OSDArray(1); + agentDataArr.Add(agentDataMap); + + OSDMap regionDataMap = new OSDMap(4); + regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle))); + regionDataMap.Add("SeedCapability", OSD.FromString(capsURL)); + regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes())); + regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port)); + + OSDArray regionDataArr = new OSDArray(1); + regionDataArr.Add(regionDataMap); + + OSDMap llsdBody = new OSDMap(3); + llsdBody.Add("Info", infoArr); + llsdBody.Add("AgentData", agentDataArr); + llsdBody.Add("RegionData", regionDataArr); + + return buildEvent("CrossedRegion", llsdBody); + } + + public static OSD TeleportFinishEvent( + ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, + uint locationID, uint flags, string capsURL, UUID agentID) + { + OSDMap info = new OSDMap(); + info.Add("AgentID", OSD.FromUUID(agentID)); + info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this? + info.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(regionHandle))); + info.Add("SeedCapability", OSD.FromString(capsURL)); + info.Add("SimAccess", OSD.FromInteger(simAccess)); + info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); + info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); + info.Add("TeleportFlags", OSD.FromBinary(1L << 4)); // AgentManager.TeleportFlags.ViaLocation + + OSDArray infoArr = new OSDArray(); + infoArr.Add(info); + + OSDMap body = new OSDMap(); + body.Add("Info", infoArr); + + return buildEvent("TeleportFinish", body); + } + + public static OSD ScriptRunningReplyEvent(UUID objectID, UUID itemID, bool running, bool mono) + { + OSDMap script = new OSDMap(); + script.Add("ObjectID", OSD.FromUUID(objectID)); + script.Add("ItemID", OSD.FromUUID(itemID)); + script.Add("Running", OSD.FromBoolean(running)); + script.Add("Mono", OSD.FromBoolean(mono)); + + OSDArray scriptArr = new OSDArray(); + scriptArr.Add(script); + + OSDMap body = new OSDMap(); + body.Add("Script", scriptArr); + + return buildEvent("ScriptRunningReply", body); + } + + public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap) + { + OSDMap body = new OSDMap(3); + body.Add("agent-id", new OSDUUID(agentID)); + body.Add("sim-ip-and-port", new OSDString(simIpAndPort)); + body.Add("seed-capability", new OSDString(seedcap)); + + return buildEvent("EstablishAgentCommunication", body); + } + + public static OSD KeepAliveEvent() + { + return buildEvent("FAKEEVENT", new OSDMap()); + } + + public static OSD AgentParams(UUID agentID, bool checkEstate, int godLevel, bool limitedToEstate) + { + OSDMap body = new OSDMap(4); + + body.Add("agent_id", new OSDUUID(agentID)); + body.Add("check_estate", new OSDInteger(checkEstate ? 1 : 0)); + body.Add("god_level", new OSDInteger(godLevel)); + body.Add("limited_to_estate", new OSDInteger(limitedToEstate ? 1 : 0)); + + return body; + } + + public static OSD InstantMessageParams(UUID fromAgent, string message, UUID toAgent, + string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID, + Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) + { + OSDMap messageParams = new OSDMap(15); + messageParams.Add("type", new OSDInteger((int)dialog)); + + OSDArray positionArray = new OSDArray(3); + positionArray.Add(OSD.FromReal(position.X)); + positionArray.Add(OSD.FromReal(position.Y)); + positionArray.Add(OSD.FromReal(position.Z)); + messageParams.Add("position", positionArray); + + messageParams.Add("region_id", new OSDUUID(UUID.Zero)); + messageParams.Add("to_id", new OSDUUID(toAgent)); + messageParams.Add("source", new OSDInteger(0)); + + OSDMap data = new OSDMap(1); + data.Add("binary_bucket", OSD.FromBinary(binaryBucket)); + messageParams.Add("data", data); + messageParams.Add("message", new OSDString(message)); + messageParams.Add("id", new OSDUUID(transactionID)); + messageParams.Add("from_name", new OSDString(fromName)); + messageParams.Add("timestamp", new OSDInteger((int)timeStamp)); + messageParams.Add("offline", new OSDInteger(offline ? 1 : 0)); + messageParams.Add("parent_estate_id", new OSDInteger(parentEstateID)); + messageParams.Add("ttl", new OSDInteger((int)ttl)); + messageParams.Add("from_id", new OSDUUID(fromAgent)); + messageParams.Add("from_group", new OSDInteger(fromGroup ? 1 : 0)); + + return messageParams; + } + + public static OSD InstantMessage(UUID fromAgent, string message, UUID toAgent, + string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID, + Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket, + bool checkEstate, int godLevel, bool limitedToEstate) + { + OSDMap im = new OSDMap(2); + im.Add("message_params", InstantMessageParams(fromAgent, message, toAgent, + fromName, dialog, timeStamp, offline, parentEstateID, + position, ttl, transactionID, fromGroup, binaryBucket)); + + im.Add("agent_params", AgentParams(fromAgent, checkEstate, godLevel, limitedToEstate)); + + return im; + } + + + public static OSD ChatterboxInvitation(UUID sessionID, string sessionName, + UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, + uint timeStamp, bool offline, int parentEstateID, Vector3 position, + uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) + { + OSDMap body = new OSDMap(5); + body.Add("session_id", new OSDUUID(sessionID)); + body.Add("from_name", new OSDString(fromName)); + body.Add("session_name", new OSDString(sessionName)); + body.Add("from_id", new OSDUUID(fromAgent)); + + body.Add("instantmessage", InstantMessage(fromAgent, message, toAgent, + fromName, dialog, timeStamp, offline, parentEstateID, position, + ttl, transactionID, fromGroup, binaryBucket, true, 0, true)); + + OSDMap chatterboxInvitation = new OSDMap(2); + chatterboxInvitation.Add("message", new OSDString("ChatterBoxInvitation")); + chatterboxInvitation.Add("body", body); + return chatterboxInvitation; + } + + public static OSD ChatterBoxSessionAgentListUpdates(UUID sessionID, + UUID agentID, bool canVoiceChat, bool isModerator, bool textMute) + { + OSDMap body = new OSDMap(); + OSDMap agentUpdates = new OSDMap(); + OSDMap infoDetail = new OSDMap(); + OSDMap mutes = new OSDMap(); + + mutes.Add("text", OSD.FromBoolean(textMute)); + infoDetail.Add("can_voice_chat", OSD.FromBoolean(canVoiceChat)); + infoDetail.Add("is_moderator", OSD.FromBoolean(isModerator)); + infoDetail.Add("mutes", mutes); + OSDMap info = new OSDMap(); + info.Add("info", infoDetail); + agentUpdates.Add(agentID.ToString(), info); + body.Add("agent_updates", agentUpdates); + body.Add("session_id", OSD.FromUUID(sessionID)); + body.Add("updates", new OSD()); + + OSDMap chatterBoxSessionAgentListUpdates = new OSDMap(); + chatterBoxSessionAgentListUpdates.Add("message", OSD.FromString("ChatterBoxSessionAgentListUpdates")); + chatterBoxSessionAgentListUpdates.Add("body", body); + + return chatterBoxSessionAgentListUpdates; + } + + public static OSD ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket) + { + OSDMap parcelProperties = new OSDMap(); + OSDMap body = new OSDMap(); + + OSDArray ageVerificationBlock = new OSDArray(); + OSDMap ageVerificationMap = new OSDMap(); + ageVerificationMap.Add("RegionDenyAgeUnverified", + OSD.FromBoolean(parcelPropertiesPacket.AgeVerificationBlock.RegionDenyAgeUnverified)); + ageVerificationBlock.Add(ageVerificationMap); + body.Add("AgeVerificationBlock", ageVerificationBlock); + + // LL sims send media info in this event queue message but it's not in the UDP + // packet we construct this event queue message from. This should be refactored in + // other areas of the code so it can all be send in the same message. Until then we will + // still send the media info via UDP + + //OSDArray mediaData = new OSDArray(); + //OSDMap mediaDataMap = new OSDMap(); + //mediaDataMap.Add("MediaDesc", OSD.FromString("")); + //mediaDataMap.Add("MediaHeight", OSD.FromInteger(0)); + //mediaDataMap.Add("MediaLoop", OSD.FromInteger(0)); + //mediaDataMap.Add("MediaType", OSD.FromString("type/type")); + //mediaDataMap.Add("MediaWidth", OSD.FromInteger(0)); + //mediaDataMap.Add("ObscureMedia", OSD.FromInteger(0)); + //mediaDataMap.Add("ObscureMusic", OSD.FromInteger(0)); + //mediaData.Add(mediaDataMap); + //body.Add("MediaData", mediaData); + + OSDArray parcelData = new OSDArray(); + OSDMap parcelDataMap = new OSDMap(); + OSDArray AABBMax = new OSDArray(3); + AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.X)); + AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Y)); + AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Z)); + parcelDataMap.Add("AABBMax", AABBMax); + + OSDArray AABBMin = new OSDArray(3); + AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.X)); + AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Y)); + AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Z)); + parcelDataMap.Add("AABBMin", AABBMin); + + parcelDataMap.Add("Area", OSD.FromInteger(parcelPropertiesPacket.ParcelData.Area)); + parcelDataMap.Add("AuctionID", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.AuctionID))); + parcelDataMap.Add("AuthBuyerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.AuthBuyerID)); + parcelDataMap.Add("Bitmap", OSD.FromBinary(parcelPropertiesPacket.ParcelData.Bitmap)); + parcelDataMap.Add("Category", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Category)); + parcelDataMap.Add("ClaimDate", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimDate)); + parcelDataMap.Add("ClaimPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimPrice)); + parcelDataMap.Add("Desc", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc))); + parcelDataMap.Add("GroupID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.GroupID)); + parcelDataMap.Add("GroupPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.GroupPrims)); + parcelDataMap.Add("IsGroupOwned", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.IsGroupOwned)); + parcelDataMap.Add("LandingType", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LandingType)); + parcelDataMap.Add("LocalID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LocalID)); + parcelDataMap.Add("MaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.MaxPrims)); + parcelDataMap.Add("MediaAutoScale", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.MediaAutoScale)); + parcelDataMap.Add("MediaID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.MediaID)); + parcelDataMap.Add("MediaURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL))); + parcelDataMap.Add("MusicURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL))); + parcelDataMap.Add("Name", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name))); + parcelDataMap.Add("OtherCleanTime", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCleanTime)); + parcelDataMap.Add("OtherCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCount)); + parcelDataMap.Add("OtherPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherPrims)); + parcelDataMap.Add("OwnerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.OwnerID)); + parcelDataMap.Add("OwnerPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OwnerPrims)); + parcelDataMap.Add("ParcelFlags", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.ParcelFlags))); + parcelDataMap.Add("ParcelPrimBonus", OSD.FromReal(parcelPropertiesPacket.ParcelData.ParcelPrimBonus)); + parcelDataMap.Add("PassHours", OSD.FromReal(parcelPropertiesPacket.ParcelData.PassHours)); + parcelDataMap.Add("PassPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PassPrice)); + parcelDataMap.Add("PublicCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PublicCount)); + parcelDataMap.Add("RegionDenyAnonymous", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyAnonymous)); + parcelDataMap.Add("RegionDenyIdentified", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyIdentified)); + parcelDataMap.Add("RegionDenyTransacted", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyTransacted)); + + parcelDataMap.Add("RegionPushOverride", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionPushOverride)); + parcelDataMap.Add("RentPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RentPrice)); + parcelDataMap.Add("RequestResult", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RequestResult)); + parcelDataMap.Add("SalePrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SalePrice)); + parcelDataMap.Add("SelectedPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelectedPrims)); + parcelDataMap.Add("SelfCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelfCount)); + parcelDataMap.Add("SequenceID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SequenceID)); + parcelDataMap.Add("SimWideMaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideMaxPrims)); + parcelDataMap.Add("SimWideTotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideTotalPrims)); + parcelDataMap.Add("SnapSelection", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.SnapSelection)); + parcelDataMap.Add("SnapshotID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.SnapshotID)); + parcelDataMap.Add("Status", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Status)); + parcelDataMap.Add("TotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.TotalPrims)); + + OSDArray UserLocation = new OSDArray(3); + UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.X)); + UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Y)); + UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Z)); + parcelDataMap.Add("UserLocation", UserLocation); + + OSDArray UserLookAt = new OSDArray(3); + UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.X)); + UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Y)); + UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Z)); + parcelDataMap.Add("UserLookAt", UserLookAt); + + parcelData.Add(parcelDataMap); + body.Add("ParcelData", parcelData); + parcelProperties.Add("body", body); + parcelProperties.Add("message", OSD.FromString("ParcelProperties")); + + return parcelProperties; + } + + public static OSD GroupMembership(AgentGroupDataUpdatePacket groupUpdatePacket) + { + OSDMap groupUpdate = new OSDMap(); + groupUpdate.Add("message", OSD.FromString("AgentGroupDataUpdate")); + + OSDMap body = new OSDMap(); + OSDArray agentData = new OSDArray(); + OSDMap agentDataMap = new OSDMap(); + agentDataMap.Add("AgentID", OSD.FromUUID(groupUpdatePacket.AgentData.AgentID)); + agentData.Add(agentDataMap); + body.Add("AgentData", agentData); + + OSDArray groupData = new OSDArray(); + + foreach (AgentGroupDataUpdatePacket.GroupDataBlock groupDataBlock in groupUpdatePacket.GroupData) + { + OSDMap groupDataMap = new OSDMap(); + groupDataMap.Add("ListInProfile", OSD.FromBoolean(false)); + groupDataMap.Add("GroupID", OSD.FromUUID(groupDataBlock.GroupID)); + groupDataMap.Add("GroupInsigniaID", OSD.FromUUID(groupDataBlock.GroupInsigniaID)); + groupDataMap.Add("Contribution", OSD.FromInteger(groupDataBlock.Contribution)); + groupDataMap.Add("GroupPowers", OSD.FromBinary(ulongToByteArray(groupDataBlock.GroupPowers))); + groupDataMap.Add("GroupName", OSD.FromString(Utils.BytesToString(groupDataBlock.GroupName))); + groupDataMap.Add("AcceptNotices", OSD.FromBoolean(groupDataBlock.AcceptNotices)); + + groupData.Add(groupDataMap); + + } + body.Add("GroupData", groupData); + groupUpdate.Add("body", body); + + return groupUpdate; + } + + } +} diff --git a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs new file mode 100644 index 0000000..fe29e0c --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Command.cs @@ -0,0 +1,216 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander +{ + /// + /// A single function call encapsulated in a class which enforces arguments when passing around as Object[]'s. + /// Used for console commands and script API generation + /// + public class Command : ICommand + { + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private List m_args = new List(); + + private Action m_command; + private string m_help; + private string m_name; + private CommandIntentions m_intentions; //A permission type system could implement this and know what a command intends on doing. + + public Command(string name, CommandIntentions intention, Action command, string help) + { + m_name = name; + m_command = command; + m_help = help; + m_intentions = intention; + } + + #region ICommand Members + + public void AddArgument(string name, string helptext, string type) + { + m_args.Add(new CommandArgument(name, helptext, type)); + } + + public string Name + { + get { return m_name; } + } + + public CommandIntentions Intentions + { + get { return m_intentions; } + } + + public string Help + { + get { return m_help; } + } + + public Dictionary Arguments + { + get + { + Dictionary tmp = new Dictionary(); + foreach (CommandArgument arg in m_args) + { + tmp.Add(arg.Name, arg.ArgumentType); + } + return tmp; + } + } + + public string ShortHelp() + { + string help = m_name; + + foreach (CommandArgument arg in m_args) + { + help += " <" + arg.Name + ">"; + } + + return help; + } + + public void ShowConsoleHelp() + { + Console.WriteLine("== " + Name + " =="); + Console.WriteLine(m_help); + Console.WriteLine("= Parameters ="); + foreach (CommandArgument arg in m_args) + { + Console.WriteLine("* " + arg.Name + " (" + arg.ArgumentType + ")"); + Console.WriteLine("\t" + arg.HelpText); + } + } + + public void Run(Object[] args) + { + Object[] cleanArgs = new Object[m_args.Count]; + + if (args.Length < cleanArgs.Length) + { + Console.WriteLine("ERROR: Missing " + (cleanArgs.Length - args.Length) + " argument(s)"); + ShowConsoleHelp(); + return; + } + if (args.Length > cleanArgs.Length) + { + Console.WriteLine("ERROR: Too many arguments for this command. Type ' help' for help."); + return; + } + + int i = 0; + foreach (Object arg in args) + { + if (string.IsNullOrEmpty(arg.ToString())) + { + Console.WriteLine("ERROR: Empty arguments are not allowed"); + return; + } + try + { + switch (m_args[i].ArgumentType) + { + case "String": + m_args[i].ArgumentValue = arg.ToString(); + break; + case "Integer": + m_args[i].ArgumentValue = Int32.Parse(arg.ToString()); + break; + case "Double": + m_args[i].ArgumentValue = Double.Parse(arg.ToString()); + break; + case "Boolean": + m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); + break; + default: + Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); + break; + } + } + catch (FormatException) + { + Console.WriteLine("ERROR: Argument number " + (i + 1) + + " (" + m_args[i].Name + ") must be a valid " + + m_args[i].ArgumentType.ToLower() + "."); + return; + } + cleanArgs[i] = m_args[i].ArgumentValue; + + i++; + } + + m_command.Invoke(cleanArgs); + } + + #endregion + } + + /// + /// A single command argument, contains name, type and at runtime, value. + /// + public class CommandArgument + { + private string m_help; + private string m_name; + private string m_type; + private Object m_val; + + public CommandArgument(string name, string help, string type) + { + m_name = name; + m_help = help; + m_type = type; + } + + public string Name + { + get { return m_name; } + } + + public string HelpText + { + get { return m_help; } + } + + public string ArgumentType + { + get { return m_type; } + } + + public Object ArgumentValue + { + get { return m_val; } + set { m_val = value; } + } + } +} diff --git a/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs new file mode 100644 index 0000000..cd905ab --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/InterfaceCommander/Commander.cs @@ -0,0 +1,182 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using log4net; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.Framework.InterfaceCommander +{ + /// + /// A class to enable modules to register console and script commands, which enforces typing and valid input. + /// + public class Commander : ICommander + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Used in runtime class generation + /// + private string m_generatedApiClassName; + + public string Name + { + get { return m_name; } + } + private string m_name; + + public string Help + { + get + { + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("=== " + m_name + " ==="); + + foreach (ICommand com in m_commands.Values) + { + sb.AppendLine("* " + Name + " " + com.Name + " - " + com.Help); + } + + return sb.ToString(); + } + } + + /// + /// Constructor + /// + /// + public Commander(string name) + { + m_name = name; + m_generatedApiClassName = m_name[0].ToString().ToUpper(); + + if (m_name.Length > 1) + m_generatedApiClassName += m_name.Substring(1); + } + + public Dictionary Commands + { + get { return m_commands; } + } + private Dictionary m_commands = new Dictionary(); + + #region ICommander Members + + public void RegisterCommand(string commandName, ICommand command) + { + m_commands[commandName] = command; + } + + /// + /// Generates a runtime C# class which can be compiled and inserted via reflection to enable modules to register new script commands + /// + /// Returns C# source code to create a binding + public string GenerateRuntimeAPI() + { + string classSrc = "\n\tpublic class " + m_generatedApiClassName + " {\n"; + foreach (ICommand com in m_commands.Values) + { + classSrc += "\tpublic void " + EscapeRuntimeAPICommand(com.Name) + "( "; + foreach (KeyValuePair arg in com.Arguments) + { + classSrc += arg.Value + " " + Util.Md5Hash(arg.Key) + ","; + } + classSrc = classSrc.Remove(classSrc.Length - 1); // Delete the last comma + classSrc += " )\n\t{\n"; + classSrc += "\t\tObject[] args = new Object[" + com.Arguments.Count.ToString() + "];\n"; + int i = 0; + foreach (KeyValuePair arg in com.Arguments) + { + classSrc += "\t\targs[" + i.ToString() + "] = " + Util.Md5Hash(arg.Key) + " " + ";\n"; + i++; + } + classSrc += "\t\tGetCommander(\"" + m_name + "\").Run(\"" + com.Name + "\", args);\n"; + classSrc += "\t}\n"; + } + classSrc += "}\n"; + + return classSrc; + } + + /// + /// Runs a specified function with attached arguments + /// *** DO NOT CALL DIRECTLY. *** + /// Call ProcessConsoleCommand instead if handling human input. + /// + /// The function name to call + /// The function parameters + public void Run(string function, object[] args) + { + m_commands[function].Run(args); + } + + public void ProcessConsoleCommand(string function, string[] args) + { + if (m_commands.ContainsKey(function)) + { + if (args.Length > 0 && args[0] == "help") + { + m_commands[function].ShowConsoleHelp(); + } + else + { + m_commands[function].Run(args); + } + } + else + { + if (function == "api") + { + m_log.Info(GenerateRuntimeAPI()); + } + else + { + if (function != "help") + Console.WriteLine("ERROR: Invalid command - No such command exists"); + + Console.Write(Help); + } + } + } + + #endregion + + private string EscapeRuntimeAPICommand(string command) + { + command = command.Replace('-', '_'); + StringBuilder tmp = new StringBuilder(command); + tmp[0] = tmp[0].ToString().ToUpper().ToCharArray()[0]; + + return tmp.ToString(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneAssetService.cs b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneAssetService.cs new file mode 100644 index 0000000..13efe6b --- /dev/null +++ b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneAssetService.cs @@ -0,0 +1,201 @@ +/** + * Copyright (c) 2008, Contributors. All rights reserved. + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Organizations nor the names of Individual + * Contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +using System; +using System.Collections.Generic; +using System.Net; +using System.Reflection; + +using log4net; +using Nini.Config; + +using OpenMetaverse; + +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Grid.AssetServer; +using OpenSim.Data; + +namespace OpenSim.Region.CoreModules.Hypergrid +{ + public class HGStandaloneAssetService : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool initialized = false; + private static bool enabled = false; + + Scene m_scene; + //AssetService m_assetService; + + #region IRegionModule interface + + public void Initialise(Scene scene, IConfigSource config) + { + if (!initialized) + { + initialized = true; + m_scene = scene; + + // This module is only on for standalones in hypergrid mode + enabled = !config.Configs["Startup"].GetBoolean("gridmode", true) && config.Configs["Startup"].GetBoolean("hypergrid", false); + } + } + + public void PostInitialise() + { + if (enabled) + { + m_log.Info("[HGStandaloneAssetService]: Starting..."); + + //m_assetService = new AssetService(m_scene); + new AssetService(m_scene); + } + } + + public void Close() + { + } + + public string Name + { + get { return "HGStandaloneAssetService"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + } + + public class AssetService + { + private IUserService m_userService; + private bool m_doLookup = false; + + public bool DoLookup + { + get { return m_doLookup; } + set { m_doLookup = value; } + } + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public AssetService(Scene m_scene) + { + AddHttpHandlers(m_scene); + m_userService = m_scene.CommsManager.UserService; + } + + protected void AddHttpHandlers(Scene m_scene) + { + IAssetDataPlugin m_assetProvider = ((AssetServerBase)m_scene.AssetCache.AssetServer).AssetProviderPlugin; + + BaseHttpServer httpServer = m_scene.CommsManager.HttpServer; + httpServer.AddStreamHandler(new GetAssetStreamHandler(m_assetProvider)); + httpServer.AddStreamHandler(new PostAssetStreamHandler(m_assetProvider)); + + } + + ///// + ///// Check that the source of an inventory request is one that we trust. + ///// + ///// + ///// + //public bool CheckTrustSource(IPEndPoint peer) + //{ + // if (m_doLookup) + // { + // m_log.InfoFormat("[GRID AGENT INVENTORY]: Checking trusted source {0}", peer); + // UriBuilder ub = new UriBuilder(m_userserver_url); + // IPAddress[] uaddrs = Dns.GetHostAddresses(ub.Host); + // foreach (IPAddress uaddr in uaddrs) + // { + // if (uaddr.Equals(peer.Address)) + // { + // return true; + // } + // } + + // m_log.WarnFormat( + // "[GRID AGENT INVENTORY]: Rejecting request since source {0} was not in the list of trusted sources", + // peer); + + // return false; + // } + // else + // { + // return true; + // } + //} + + /// + /// Check that the source of an inventory request for a particular agent is a current session belonging to + /// that agent. + /// + /// + /// + /// + public bool CheckAuthSession(string session_id, string avatar_id) + { + if (m_doLookup) + { + m_log.InfoFormat("[HGStandaloneInvService]: checking authed session {0} {1}", session_id, avatar_id); + UUID userID = UUID.Zero; + UUID sessionID = UUID.Zero; + UUID.TryParse(avatar_id, out userID); + UUID.TryParse(session_id, out sessionID); + if (userID.Equals(UUID.Zero) || sessionID.Equals(UUID.Zero)) + { + m_log.Info("[HGStandaloneInvService]: Invalid user or session id " + avatar_id + "; " + session_id); + return false; + } + UserProfileData userProfile = m_userService.GetUserProfile(userID); + if (userProfile != null && userProfile.CurrentAgent != null && + userProfile.CurrentAgent.SessionID == sessionID) + { + m_log.Info("[HGStandaloneInvService]: user is logged in and session is valid. Authorizing access."); + return true; + } + + m_log.Warn("[HGStandaloneInvService]: unknown user or session_id, request rejected"); + return false; + } + else + { + return true; + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryService.cs b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryService.cs new file mode 100644 index 0000000..dfc859e --- /dev/null +++ b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryService.cs @@ -0,0 +1,314 @@ +/** + * Copyright (c) 2008, Contributors. All rights reserved. + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Organizations nor the names of Individual + * Contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +using System; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Hypergrid +{ + public class HGStandaloneInventoryService : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool initialized = false; + private static bool enabled = false; + + Scene m_scene; + //InventoryService m_inventoryService; + + #region IRegionModule interface + + public void Initialise(Scene scene, IConfigSource config) + { + if (!initialized) + { + initialized = true; + m_scene = scene; + + // This module is only on for standalones + enabled = !config.Configs["Startup"].GetBoolean("gridmode", true) && config.Configs["Startup"].GetBoolean("hypergrid", false); + } + } + + public void PostInitialise() + { + if (enabled) + { + m_log.Info("[HGStandaloneInvService]: Starting..."); + //m_inventoryService = new InventoryService(m_scene); + new InventoryService(m_scene); + } + } + + public void Close() + { + } + + public string Name + { + get { return "HGStandaloneInventoryService"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + } + + public class InventoryService + { + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private InventoryServiceBase m_inventoryService; + private IUserService m_userService; + private bool m_doLookup = false; + + public bool DoLookup + { + get { return m_doLookup; } + set { m_doLookup = value; } + } + + public InventoryService(Scene m_scene) + { + m_inventoryService = (InventoryServiceBase)m_scene.CommsManager.SecureInventoryService; + m_userService = m_scene.CommsManager.UserService; + AddHttpHandlers(m_scene); + } + + protected void AddHttpHandlers(Scene m_scene) + { + BaseHttpServer httpServer = m_scene.CommsManager.HttpServer; + + httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/GetInventory/", GetUserInventory, CheckAuthSession)); + + httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/NewFolder/", m_inventoryService.AddFolder, CheckAuthSession)); + + httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/UpdateFolder/", m_inventoryService.UpdateFolder, CheckAuthSession)); + + httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/MoveFolder/", m_inventoryService.MoveFolder, CheckAuthSession)); + + httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/PurgeFolder/", m_inventoryService.PurgeFolder, CheckAuthSession)); + + httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/NewItem/", m_inventoryService.AddItem, CheckAuthSession)); + + httpServer.AddStreamHandler( + new RestDeserialiseSecureHandler( + "POST", "/DeleteItem/", m_inventoryService.DeleteItem, CheckAuthSession)); + + //// WARNING: Root folders no longer just delivers the root and immediate child folders (e.g + //// system folders such as Objects, Textures), but it now returns the entire inventory skeleton. + //// It would have been better to rename this request, but complexities in the BaseHttpServer + //// (e.g. any http request not found is automatically treated as an xmlrpc request) make it easier + //// to do this for now. + //m_scene.AddStreamHandler( + // new RestDeserialiseTrustedHandler> + // ("POST", "/RootFolders/", GetInventorySkeleton, CheckTrustSource)); + + //// for persistent active gestures + //m_scene.AddStreamHandler( + // new RestDeserialiseTrustedHandler> + // ("POST", "/ActiveGestures/", GetActiveGestures, CheckTrustSource)); + } + + + ///// + ///// Check that the source of an inventory request is one that we trust. + ///// + ///// + ///// + //public bool CheckTrustSource(IPEndPoint peer) + //{ + // if (m_doLookup) + // { + // m_log.InfoFormat("[GRID AGENT INVENTORY]: Checking trusted source {0}", peer); + // UriBuilder ub = new UriBuilder(m_userserver_url); + // IPAddress[] uaddrs = Dns.GetHostAddresses(ub.Host); + // foreach (IPAddress uaddr in uaddrs) + // { + // if (uaddr.Equals(peer.Address)) + // { + // return true; + // } + // } + + // m_log.WarnFormat( + // "[GRID AGENT INVENTORY]: Rejecting request since source {0} was not in the list of trusted sources", + // peer); + + // return false; + // } + // else + // { + // return true; + // } + //} + + /// + /// Check that the source of an inventory request for a particular agent is a current session belonging to + /// that agent. + /// + /// + /// + /// + public bool CheckAuthSession(string session_id, string avatar_id) + { + if (m_doLookup) + { + m_log.InfoFormat("[HGStandaloneInvService]: checking authed session {0} {1}", session_id, avatar_id); + UUID userID = UUID.Zero; + UUID sessionID = UUID.Zero; + UUID.TryParse(avatar_id, out userID); + UUID.TryParse(session_id, out sessionID); + if (userID.Equals(UUID.Zero) || sessionID.Equals(UUID.Zero)) + { + m_log.Info("[HGStandaloneInvService]: Invalid user or session id " + avatar_id + "; " + session_id); + return false; + } + UserProfileData userProfile = m_userService.GetUserProfile(userID); + if (userProfile != null && userProfile.CurrentAgent != null && + userProfile.CurrentAgent.SessionID == sessionID) + { + m_log.Info("[HGStandaloneInvService]: user is logged in and session is valid. Authorizing access."); + return true; + } + + m_log.Warn("[HGStandaloneInvService]: unknown user or session_id, request rejected"); + return false; + } + else + { + return true; + } + } + + + /// + /// Return a user's entire inventory + /// + /// + /// The user's inventory. If an inventory cannot be found then an empty collection is returned. + public InventoryCollection GetUserInventory(Guid rawUserID) + { + UUID userID = new UUID(rawUserID); + + m_log.Info("[HGStandaloneInvService]: Processing request for inventory of " + userID); + + // Uncomment me to simulate a slow responding inventory server + //Thread.Sleep(16000); + + InventoryCollection invCollection = new InventoryCollection(); + + List allFolders = ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID); + + if (null == allFolders) + { + m_log.WarnFormat("[HGStandaloneInvService]: No inventory found for user {0}", rawUserID); + + return invCollection; + } + + List allItems = new List(); + + foreach (InventoryFolderBase folder in allFolders) + { + List items = ((InventoryServiceBase)m_inventoryService).RequestFolderItems(folder.ID); + + if (items != null) + { + allItems.InsertRange(0, items); + } + } + + invCollection.UserID = userID; + invCollection.Folders = allFolders; + invCollection.Items = allItems; + + // foreach (InventoryFolderBase folder in invCollection.Folders) + // { + // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back folder {0} {1}", folder.Name, folder.ID); + // } + // + // foreach (InventoryItemBase item in invCollection.Items) + // { + // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder); + // } + + m_log.InfoFormat( + "[HGStandaloneInvService]: Sending back inventory response to user {0} containing {1} folders and {2} items", + invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count); + + return invCollection; + } + + /// + /// Guid to UUID wrapper for same name IInventoryServices method + /// + /// + /// + public List GetInventorySkeleton(Guid rawUserID) + { + UUID userID = new UUID(rawUserID); + return ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID); + } + + public List GetActiveGestures(Guid rawUserID) + { + UUID userID = new UUID(rawUserID); + + m_log.InfoFormat("[HGStandaloneInvService]: fetching active gestures for user {0}", userID); + + return ((InventoryServiceBase)m_inventoryService).GetActiveGestures(userID); + } + } +} diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs new file mode 100644 index 0000000..5540cc3 --- /dev/null +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2008, Contributors. All rights reserved. + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Organizations nor the names of Individual + * Contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Net; +using System.Reflection; +using System.Threading; +using OpenMetaverse; +using OpenMetaverse.Imaging; +using OpenMetaverse.StructuredData; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; + +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Types; +using OpenSim.Region.CoreModules.World.WorldMap; +using Caps = OpenSim.Framework.Communications.Capabilities.Caps; + +using OSD = OpenMetaverse.StructuredData.OSD; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; + +namespace OpenSim.Region.CoreModules.Hypergrid +{ + public class HGWorldMapModule : WorldMapModule, IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #region IRegionModule Members + + public override void Initialise(Scene scene, IConfigSource config) + { + IConfig startupConfig = config.Configs["Startup"]; + if (startupConfig.GetString("WorldMapModule", "WorldMap") == "HGWorldMap") + m_Enabled = true; + + if (!m_Enabled) + return; + m_log.Info("[HGMap] Initializing..."); + m_scene = scene; + } + + + public override string Name + { + get { return "HGWorldMap"; } + } + + + #endregion + + /// + /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates + /// + /// + /// + /// + /// + public override void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + { + // + // WARNING!!! COPY & PASTE FROM SUPERCLASS + // The only difference is at the very end + // + + m_log.Info("[HGMap]: Request map blocks " + minX + "-" + maxX + " " + minY + "-" + maxY); + + //m_scene.ForEachScenePresence(delegate (ScenePresence sp) { + // if (!sp.IsChildAgent && sp.UUID == remoteClient.AgentId) + // { + // Console.WriteLine("XXX Root agent"); + // DoRequestMapBlocks(remoteClient, minX, minY, maxX, maxY, flag); + // } + //}; + + List mapBlocks; + if ((flag & 0x10000) != 0) // user clicked on the map a tile that isn't visible + { + List response = new List(); + + // this should return one mapblock at most. But make sure: Look whether the one we requested is in there + mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); + if (mapBlocks != null) + { + foreach (MapBlockData block in mapBlocks) + { + if (block.X == minX && block.Y == minY) + { + // found it => add it to response + response.Add(block); + break; + } + } + } + response = mapBlocks; + if (response.Count == 0) + { + // response still empty => couldn't find the map-tile the user clicked on => tell the client + MapBlockData block = new MapBlockData(); + block.X = (ushort)minX; + block.Y = (ushort)minY; + block.Access = 254; // == not there + response.Add(block); + } + remoteClient.SendMapBlock(response, 0); + } + else + { + // normal mapblock request. Use the provided values + mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, maxX + 4, maxY + 4); + + // Different from super + FillInMap(mapBlocks, minX, minY, maxX, maxY); + // + + remoteClient.SendMapBlock(mapBlocks, flag); + } + } + + + private void FillInMap(List mapBlocks, int minX, int minY, int maxX, int maxY) + { + for (int x = minX; x <= maxX; x++) + for (int y = minY; y <= maxY; y++) + { + MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); }); + if (mblock == null) + { + mblock = new MapBlockData(); + mblock.X = (ushort)x; + mblock.Y = (ushort)y; + mblock.Name = ""; + mblock.Access = 254; // not here??? + mblock.MapImageId = UUID.Zero; + mapBlocks.Add(mblock); + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs new file mode 100644 index 0000000..2e1675b --- /dev/null +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs @@ -0,0 +1,1273 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Reflection; +using System.Threading; +using System.Web; + +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Packets; + +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +using OSD = OpenMetaverse.StructuredData.OSD; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; + +namespace OpenSim.Region.CoreModules.InterGrid +{ + public struct OGPState + { + public string first_name; + public string last_name; + public UUID agent_id; + public UUID local_agent_id; + public UUID region_id; + public uint circuit_code; + public UUID secure_session_id; + public UUID session_id; + public bool agent_access; + public string sim_access; + public uint god_level; + public bool god_overide; + public bool identified; + public bool transacted; + public bool age_verified; + public bool allow_redirect; + public int limited_to_estate; + public string inventory_host; + public bool src_can_see_mainland; + public int src_estate_id; + public int src_version; + public int src_parent_estate_id; + public bool visible_to_parent; + public string teleported_into_region; + } + + public class OpenGridProtocolModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private List m_scene = new List(); + + private Dictionary CapsLoginID = new Dictionary(); + private Dictionary m_OGPState = new Dictionary(); + private Dictionary m_loginToRegionState = new Dictionary(); + + + private string LastNameSuffix = "_EXTERNAL"; + private string FirstNamePrefix = ""; + private string httpsCN = ""; + private bool httpSSL = false; + private uint httpsslport = 0; + private bool GridMode = false; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + bool enabled = false; + IConfig cfg = null; + IConfig httpcfg = null; + IConfig startupcfg = null; + try + { + cfg = config.Configs["OpenGridProtocol"]; + } catch (NullReferenceException) + { + enabled = false; + } + + try + { + httpcfg = config.Configs["Network"]; + } + catch (NullReferenceException) + { + + } + try + { + startupcfg = config.Configs["Startup"]; + } + catch (NullReferenceException) + { + + } + + if (startupcfg != null) + { + GridMode = enabled = startupcfg.GetBoolean("gridmode", false); + } + + if (cfg != null) + { + enabled = cfg.GetBoolean("ogp_enabled", false); + LastNameSuffix = cfg.GetString("ogp_lastname_suffix", "_EXTERNAL"); + FirstNamePrefix = cfg.GetString("ogp_firstname_prefix", ""); + if (enabled) + { + m_log.Warn("[OGP]: Open Grid Protocol is on, Listening for Clients on /agent/"); + lock (m_scene) + { + if (m_scene.Count == 0) + { + scene.CommsManager.HttpServer.AddLLSDHandler("/agent/", ProcessAgentDomainMessage); + scene.CommsManager.HttpServer.AddLLSDHandler("/", ProcessRegionDomainSeed); + try + { + ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation; + } + catch (NotImplementedException) + { + try + { +#pragma warning disable 0612, 0618 + // Mono does not implement the ServicePointManager.ServerCertificateValidationCallback yet! Don't remove this! + ServicePointManager.CertificatePolicy = new MonoCert(); +#pragma warning restore 0612, 0618 + } + catch (Exception) + { + m_log.Error("[OGP]: Certificate validation handler change not supported. You may get ssl certificate validation errors teleporting from your region to some SSL regions."); + } + } + + } + // can't pick the region 'agent' because it would conflict with our agent domain handler + // a zero length region name would conflict with are base region seed cap + if (!SceneListDuplicateCheck(scene.RegionInfo.RegionName) && scene.RegionInfo.RegionName.ToLower() != "agent" && scene.RegionInfo.RegionName.Length > 0) + { + scene.CommsManager.HttpServer.AddLLSDHandler( + "/" + HttpUtility.UrlPathEncode(scene.RegionInfo.RegionName.ToLower()), + ProcessRegionDomainSeed); + } + + if (!m_scene.Contains(scene)) + m_scene.Add(scene); + } + } + } + lock (m_scene) + { + if (m_scene.Count == 1) + { + if (httpcfg != null) + { + httpSSL = httpcfg.GetBoolean("http_listener_ssl", false); + httpsCN = httpcfg.GetString("http_listener_cn", scene.RegionInfo.ExternalHostName); + if (httpsCN.Length == 0) + httpsCN = scene.RegionInfo.ExternalHostName; + httpsslport = (uint)httpcfg.GetInt("http_listener_sslport",((int)scene.RegionInfo.HttpPort + 1)); + } + } + } + } + + public void PostInitialise() + { + } + + public void Close() + { + //scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; + } + + public string Name + { + get { return "OpenGridProtocolModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + public OSD ProcessRegionDomainSeed(string path, OSD request, string endpoint) + { + string[] pathSegments = path.Split('/'); + + if (pathSegments.Length <= 1) + { + return GenerateNoHandlerMessage(); + + } + + return GenerateRezAvatarRequestMessage(pathSegments[1]); + + + + //m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}", + // path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]); + //return new OSDMap(); + + } + + public OSD ProcessAgentDomainMessage(string path, OSD request, string endpoint) + { + // /agent/* + + string[] pathSegments = path.Split('/'); + if (pathSegments.Length <= 1) + { + return GenerateNoHandlerMessage(); + + } + if (pathSegments[0].Length == 0 && pathSegments[1].Length == 0) + { + return GenerateRezAvatarRequestMessage(""); + } + m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}", + path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]); + + switch (pathSegments[pathSegments.Length - 1]) + { + case "rez_avatar": + return RezAvatarMethod(path, request); + //break; + case "derez_avatar": + return DerezAvatarMethod(path, request); + //break; + + } + if (path.Length < 2) + { + return GenerateNoHandlerMessage(); + } + + switch (pathSegments[pathSegments.Length - 2] + "/" + pathSegments[pathSegments.Length - 1]) + { + case "rez_avatar/rez": + return RezAvatarMethod(path, request); + //break; + case "rez_avatar/request": + return RequestRezAvatarMethod(path, request); + case "rez_avatar/place": + return RequestRezAvatarMethod(path, request); + case "rez_avatar/derez": + return DerezAvatarMethod(path, request); + //break; + default: + return GenerateNoHandlerMessage(); + } + //return null; + } + + private OSD GenerateRezAvatarRequestMessage(string regionname) + { + Scene region = null; + bool usedroot = false; + + if (regionname.Length == 0) + { + region = GetRootScene(); + usedroot = true; + } + else + { + region = GetScene(HttpUtility.UrlDecode(regionname).ToLower()); + } + + // this shouldn't happen since we don't listen for a region that is down.. but + // it might if the region was taken down or is in the middle of restarting + + if (region == null) + { + region = GetRootScene(); + usedroot = true; + } + + UUID statekeeper = UUID.Random(); + + + + + RegionInfo reg = region.RegionInfo; + + OSDMap responseMap = new OSDMap(); + string rezHttpProtocol = "http://"; + //string regionCapsHttpProtocol = "http://"; + string httpaddr = reg.ExternalHostName; + string urlport = reg.HttpPort.ToString(); + string requestpath = "/agent/" + statekeeper + "/rez_avatar/request"; + + if (!usedroot) + { + lock (m_loginToRegionState) + { + if (!m_loginToRegionState.ContainsKey(requestpath)) + { + m_loginToRegionState.Add(requestpath, region.RegionInfo.RegionName.ToLower()); + } + } + } + + if (httpSSL) + { + rezHttpProtocol = "https://"; + //regionCapsHttpProtocol = "https://"; + urlport = httpsslport.ToString(); + + if (httpsCN.Length > 0) + httpaddr = httpsCN; + } + + responseMap["connect"] = OSD.FromBoolean(true); + OSDMap capabilitiesMap = new OSDMap(); + capabilitiesMap["rez_avatar/request"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + requestpath); + responseMap["capabilities"] = capabilitiesMap; + + return responseMap; + } + + // Using OpenSim.Framework.Communications.Capabilities.Caps here one time.. + // so the long name is probably better then a using statement + public void OnRegisterCaps(UUID agentID, OpenSim.Framework.Communications.Capabilities.Caps caps) + { + /* If we ever want to register our own caps here.... + * + string capsBase = "/CAPS/" + caps.CapsObjectPath; + caps.RegisterHandler("CAPNAME", + new RestStreamHandler("POST", capsBase + CAPSPOSTFIX!, + delegate(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return METHODHANDLER(request, path, param, + agentID, caps); + })); + + * + */ + } + + public OSD RequestRezAvatarMethod(string path, OSD request) + { + //System.Console.WriteLine("[REQUESTREZAVATAR]: " + request.ToString()); + + OSDMap requestMap = (OSDMap)request; + + + Scene homeScene = null; + + lock (m_loginToRegionState) + { + if (m_loginToRegionState.ContainsKey(path)) + { + homeScene = GetScene(m_loginToRegionState[path]); + m_loginToRegionState.Remove(path); + + if (homeScene == null) + homeScene = GetRootScene(); + } + else + { + homeScene = GetRootScene(); + } + } + + // Homescene is still null, we must have no regions that are up + if (homeScene == null) + return GenerateNoHandlerMessage(); + + RegionInfo reg = homeScene.RegionInfo; + ulong regionhandle = GetOSCompatibleRegionHandle(reg); + //string RegionURI = reg.ServerURI; + //int RegionPort = (int)reg.HttpPort; + + UUID RemoteAgentID = requestMap["agent_id"].AsUUID(); + + // will be used in the future. The client always connects with the aditi agentid currently + UUID LocalAgentID = RemoteAgentID; + + string FirstName = requestMap["first_name"].AsString(); + string LastName = requestMap["last_name"].AsString(); + + FirstName = FirstNamePrefix + FirstName; + LastName = LastName + LastNameSuffix; + + OGPState userState = GetOGPState(LocalAgentID); + + userState.first_name = requestMap["first_name"].AsString(); + userState.last_name = requestMap["last_name"].AsString(); + userState.age_verified = requestMap["age_verified"].AsBoolean(); + userState.transacted = requestMap["transacted"].AsBoolean(); + userState.agent_access = requestMap["agent_access"].AsBoolean(); + userState.allow_redirect = requestMap["allow_redirect"].AsBoolean(); + userState.identified = requestMap["identified"].AsBoolean(); + userState.god_level = (uint)requestMap["god_level"].AsInteger(); + userState.sim_access = requestMap["sim_access"].AsString(); + userState.agent_id = RemoteAgentID; + userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger(); + userState.src_can_see_mainland = requestMap["src_can_see_mainland"].AsBoolean(); + userState.src_estate_id = requestMap["src_estate_id"].AsInteger(); + userState.local_agent_id = LocalAgentID; + userState.teleported_into_region = reg.RegionName.ToLower(); + + UpdateOGPState(LocalAgentID, userState); + + OSDMap responseMap = new OSDMap(); + + if (RemoteAgentID == UUID.Zero) + { + responseMap["connect"] = OSD.FromBoolean(false); + responseMap["message"] = OSD.FromString("No agent ID was specified in rez_avatar/request"); + m_log.Error("[OGP]: rez_avatar/request failed because no avatar UUID was provided in the request body"); + return responseMap; + } + + responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName); + + // DEPRECIATED + responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString()); + + responseMap["connect"] = OSD.FromBoolean(true); + responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port); + responseMap["region_x"] = OSD.FromInteger(reg.RegionLocX * (uint)Constants.RegionSize); // LLX + responseMap["region_y"] = OSD.FromInteger(reg.RegionLocY * (uint)Constants.RegionSize); // LLY + responseMap["region_id"] = OSD.FromUUID(reg.originRegionID); + responseMap["sim_access"] = OSD.FromString((reg.RegionSettings.Maturity == 1) ? "Mature" : "PG"); + + // Generate a dummy agent for the user so we can get back a CAPS path + AgentCircuitData agentData = new AgentCircuitData(); + agentData.AgentID = LocalAgentID; + agentData.BaseFolder = UUID.Zero; + agentData.CapsPath = CapsUtil.GetRandomCapsObjectPath(); + agentData.child = false; + agentData.circuitcode = (uint)(Util.RandomClass.Next()); + agentData.firstname = FirstName; + agentData.lastname = LastName; + agentData.SecureSessionID = UUID.Random(); + agentData.SessionID = UUID.Random(); + agentData.startpos = new Vector3(128f, 128f, 100f); + + // Pre-Fill our region cache with information on the agent. + UserAgentData useragent = new UserAgentData(); + useragent.AgentIP = "unknown"; + useragent.AgentOnline = true; + useragent.AgentPort = (uint)0; + useragent.Handle = regionhandle; + useragent.InitialRegion = reg.originRegionID; + useragent.LoginTime = Util.UnixTimeSinceEpoch(); + useragent.LogoutTime = 0; + useragent.Position = agentData.startpos; + useragent.Region = reg.originRegionID; + useragent.SecureSessionID = agentData.SecureSessionID; + useragent.SessionID = agentData.SessionID; + + UserProfileData userProfile = new UserProfileData(); + userProfile.AboutText = "OGP User"; + userProfile.CanDoMask = (uint)0; + userProfile.Created = Util.UnixTimeSinceEpoch(); + userProfile.CurrentAgent = useragent; + userProfile.CustomType = "OGP"; + userProfile.FirstLifeAboutText = "I'm testing OpenGrid Protocol"; + userProfile.FirstLifeImage = UUID.Zero; + userProfile.FirstName = agentData.firstname; + userProfile.GodLevel = 0; + userProfile.HomeLocation = agentData.startpos; + userProfile.HomeLocationX = agentData.startpos.X; + userProfile.HomeLocationY = agentData.startpos.Y; + userProfile.HomeLocationZ = agentData.startpos.Z; + userProfile.HomeLookAt = Vector3.Zero; + userProfile.HomeLookAtX = userProfile.HomeLookAt.X; + userProfile.HomeLookAtY = userProfile.HomeLookAt.Y; + userProfile.HomeLookAtZ = userProfile.HomeLookAt.Z; + userProfile.HomeRegion = reg.RegionHandle; + userProfile.HomeRegionID = reg.originRegionID; + userProfile.HomeRegionX = reg.RegionLocX; + userProfile.HomeRegionY = reg.RegionLocY; + userProfile.ID = agentData.AgentID; + userProfile.Image = UUID.Zero; + userProfile.LastLogin = Util.UnixTimeSinceEpoch(); + userProfile.Partner = UUID.Zero; + userProfile.PasswordHash = "$1$"; + userProfile.PasswordSalt = ""; + userProfile.RootInventoryFolderID = UUID.Zero; + userProfile.SurName = agentData.lastname; + userProfile.UserAssetURI = homeScene.CommsManager.NetworkServersInfo.AssetURL; + userProfile.UserFlags = 0; + userProfile.UserInventoryURI = homeScene.CommsManager.NetworkServersInfo.InventoryURL; + userProfile.WantDoMask = 0; + userProfile.WebLoginKey = UUID.Random(); + + // Do caps registration + // get seed capagentData.firstname = FirstName;agentData.lastname = LastName; + if (homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID) == null && !GridMode) + { + homeScene.CommsManager.UserAdminService.AddUser( + agentData.firstname, agentData.lastname, CreateRandomStr(7), "", + homeScene.RegionInfo.RegionLocX, homeScene.RegionInfo.RegionLocY, agentData.AgentID); + + UserProfileData userProfile2 = homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID); + if (userProfile2 != null) + { + userProfile = userProfile2; + userProfile.AboutText = "OGP USER"; + userProfile.FirstLifeAboutText = "OGP USER"; + homeScene.CommsManager.UserService.UpdateUserProfile(userProfile); + } + } + + // Stick our data in the cache so the region will know something about us + homeScene.CommsManager.UserProfileCacheService.PreloadUserCache(agentData.AgentID, userProfile); + + // Call 'new user' event handler + homeScene.NewUserConnection(agentData); + + //string raCap = string.Empty; + + UUID AvatarRezCapUUID = LocalAgentID; + string rezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/rez"; + string derezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/derez"; + // Get a reference to the user's cap so we can pull out the Caps Object Path + OpenSim.Framework.Communications.Capabilities.Caps userCap + = homeScene.CapsModule.GetCapsHandlerForUser(agentData.AgentID); + + string rezHttpProtocol = "http://"; + string regionCapsHttpProtocol = "http://"; + string httpaddr = reg.ExternalHostName; + string urlport = reg.HttpPort.ToString(); + + if (httpSSL) + { + rezHttpProtocol = "https://"; + regionCapsHttpProtocol = "https://"; + urlport = httpsslport.ToString(); + + if (httpsCN.Length > 0) + httpaddr = httpsCN; + } + + // DEPRECIATED + responseMap["seed_capability"] + = OSD.FromString( + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + + // REPLACEMENT + responseMap["region_seed_capability"] + = OSD.FromString( + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + + responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); + responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); + responseMap["rez_avatar/derez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + derezAvatarPath); + + // Add the user to the list of CAPS that are outstanding. + // well allow the caps hosts in this dictionary + lock (CapsLoginID) + { + if (CapsLoginID.ContainsKey(rezAvatarPath)) + { + CapsLoginID[rezAvatarPath] = agentData; + + // This is a joke, if you didn't notice... It's so unlikely to happen, that I'll print this message if it does occur! + m_log.Error("[OGP]: Holy anomoly batman! Caps path already existed! All the UUID Duplication worries were founded!"); + } + else + { + CapsLoginID.Add(rezAvatarPath, agentData); + } + } + + //System.Console.WriteLine("Response:" + responseMap.ToString()); + return responseMap; + } + + public OSD RezAvatarMethod(string path, OSD request) + { + m_log.WarnFormat("[REZAVATAR]: {0}", request.ToString()); + + OSDMap responseMap = new OSDMap(); + + AgentCircuitData userData = null; + + // Only people we've issued a cap can go further + if (TryGetAgentCircuitData(path,out userData)) + { + OSDMap requestMap = (OSDMap)request; + + // take these values to start. There's a few more + UUID SecureSessionID=requestMap["secure_session_id"].AsUUID(); + UUID SessionID = requestMap["session_id"].AsUUID(); + int circuitcode = requestMap["circuit_code"].AsInteger(); + OSDArray Parameter = new OSDArray(); + if (requestMap.ContainsKey("parameter")) + { + Parameter = (OSDArray)requestMap["parameter"]; + } + + //int version = 1; + int estateID = 1; + int parentEstateID = 1; + UUID regionID = UUID.Zero; + bool visibleToParent = true; + + for (int i = 0; i < Parameter.Count; i++) + { + OSDMap item = (OSDMap)Parameter[i]; +// if (item.ContainsKey("version")) +// { +// version = item["version"].AsInteger(); +// } + if (item.ContainsKey("estate_id")) + { + estateID = item["estate_id"].AsInteger(); + } + if (item.ContainsKey("parent_estate_id")) + { + parentEstateID = item["parent_estate_id"].AsInteger(); + + } + if (item.ContainsKey("region_id")) + { + regionID = item["region_id"].AsUUID(); + + } + if (item.ContainsKey("visible_to_parent")) + { + visibleToParent = item["visible_to_parent"].AsBoolean(); + } + } + //Update our Circuit data with the real values + userData.SecureSessionID = SecureSessionID; + userData.SessionID = SessionID; + + OGPState userState = GetOGPState(userData.AgentID); + + // Locate a home scene suitable for the user. + Scene homeScene = null; + + homeScene = GetScene(userState.teleported_into_region); + + if (homeScene == null) + homeScene = GetRootScene(); + + if (homeScene != null) + { + // Get a referenceokay - to their Cap object so we can pull out the capobjectroot + OpenSim.Framework.Communications.Capabilities.Caps userCap + = homeScene.CapsModule.GetCapsHandlerForUser(userData.AgentID); + + //Update the circuit data in the region so this user is authorized + homeScene.UpdateCircuitData(userData); + homeScene.ChangeCircuitCode(userData.circuitcode,(uint)circuitcode); + + // Load state + + + // Keep state changes + userState.first_name = requestMap["first_name"].AsString(); + userState.secure_session_id = requestMap["secure_session_id"].AsUUID(); + userState.age_verified = requestMap["age_verified"].AsBoolean(); + userState.region_id = homeScene.RegionInfo.originRegionID; // replace 0000000 with our regionid + userState.transacted = requestMap["transacted"].AsBoolean(); + userState.agent_access = requestMap["agent_access"].AsBoolean(); + userState.inventory_host = requestMap["inventory_host"].AsString(); + userState.identified = requestMap["identified"].AsBoolean(); + userState.session_id = requestMap["session_id"].AsUUID(); + userState.god_level = (uint)requestMap["god_level"].AsInteger(); + userState.last_name = requestMap["last_name"].AsString(); + userState.god_overide = requestMap["god_override"].AsBoolean(); + userState.circuit_code = (uint)requestMap["circuit_code"].AsInteger(); + userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger(); + userState.src_estate_id = estateID; + userState.region_id = regionID; + userState.src_parent_estate_id = parentEstateID; + userState.visible_to_parent = visibleToParent; + + // Save state changes + UpdateOGPState(userData.AgentID, userState); + + // Get the region information for the home region. + RegionInfo reg = homeScene.RegionInfo; + + // Dummy positional and look at info.. we don't have it. + OSDArray PositionArray = new OSDArray(); + PositionArray.Add(OSD.FromInteger(128)); + PositionArray.Add(OSD.FromInteger(128)); + PositionArray.Add(OSD.FromInteger(40)); + + OSDArray LookAtArray = new OSDArray(); + LookAtArray.Add(OSD.FromInteger(1)); + LookAtArray.Add(OSD.FromInteger(1)); + LookAtArray.Add(OSD.FromInteger(1)); + + // Our region's X and Y position in OpenSimulator space. + uint fooX = reg.RegionLocX; + uint fooY = reg.RegionLocY; + m_log.InfoFormat("[OGP]: region x({0}) region y({1})", fooX, fooY); + m_log.InfoFormat("[OGP]: region http {0} {1}", reg.ServerURI, reg.HttpPort); + m_log.InfoFormat("[OGO]: region UUID {0} ", reg.RegionID); + + // Convert the X and Y position to LL space + responseMap["region_x"] = OSD.FromInteger(fooX * (uint)Constants.RegionSize); // convert it to LL X + responseMap["region_y"] = OSD.FromInteger(fooY * (uint)Constants.RegionSize); // convert it to LL Y + + // Give em a new seed capability + responseMap["seed_capability"] = OSD.FromString("http://" + reg.ExternalHostName + ":" + reg.HttpPort + "/CAPS/" + userCap.CapsObjectPath + "0000/"); + responseMap["region"] = OSD.FromUUID(reg.originRegionID); + responseMap["look_at"] = LookAtArray; + + responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port); + responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName);// + ":" + reg.InternalEndPoint.Port.ToString()); + + // DEPRECIATED + responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString()); + + responseMap["session_id"] = OSD.FromUUID(SessionID); + responseMap["secure_session_id"] = OSD.FromUUID(SecureSessionID); + responseMap["circuit_code"] = OSD.FromInteger(circuitcode); + + responseMap["position"] = PositionArray; + + responseMap["region_id"] = OSD.FromUUID(reg.originRegionID); + + responseMap["sim_access"] = OSD.FromString("Mature"); + + responseMap["connect"] = OSD.FromBoolean(true); + + + + m_log.InfoFormat("[OGP]: host: {0}, IP {1}", responseMap["sim_host"].ToString(), responseMap["sim_ip"].ToString()); + } + } + + return responseMap; + } + + public OSD DerezAvatarMethod(string path, OSD request) + { + m_log.ErrorFormat("DerezPath: {0}, Request: {1}", path, request.ToString()); + + //LLSD llsdResponse = null; + OSDMap responseMap = new OSDMap(); + + string[] PathArray = path.Split('/'); + m_log.InfoFormat("[OGP]: prefix {0}, uuid {1}, suffix {2}", PathArray[1], PathArray[2], PathArray[3]); + string uuidString = PathArray[2]; + m_log.InfoFormat("[OGP]: Request to Derez avatar with UUID {0}", uuidString); + UUID userUUID = UUID.Zero; + if (UUID.TryParse(uuidString, out userUUID)) + { + UUID RemoteID = (UUID)uuidString; + UUID LocalID = RemoteID; + // FIXME: TODO: Routine to map RemoteUUIDs to LocalUUIds + // would be done already.. but the client connects with the Aditi UUID + // regardless over the UDP stack + + OGPState userState = GetOGPState(LocalID); + if (userState.agent_id != UUID.Zero) + { + //OSDMap outboundRequestMap = new OSDMap(); + OSDMap inboundRequestMap = (OSDMap)request; + string rezAvatarString = inboundRequestMap["rez_avatar"].AsString(); + if (rezAvatarString.Length == 0) + { + rezAvatarString = inboundRequestMap["rez_avatar/rez"].AsString(); + } + OSDArray LookAtArray = new OSDArray(); + LookAtArray.Add(OSD.FromInteger(1)); + LookAtArray.Add(OSD.FromInteger(1)); + LookAtArray.Add(OSD.FromInteger(1)); + + OSDArray PositionArray = new OSDArray(); + PositionArray.Add(OSD.FromInteger(128)); + PositionArray.Add(OSD.FromInteger(128)); + PositionArray.Add(OSD.FromInteger(40)); + + OSDArray lookArray = new OSDArray(); + lookArray.Add(OSD.FromInteger(128)); + lookArray.Add(OSD.FromInteger(128)); + lookArray.Add(OSD.FromInteger(40)); + + responseMap["connect"] = OSD.FromBoolean(true);// it's okay to give this user up + responseMap["look_at"] = LookAtArray; + + m_log.WarnFormat("[OGP]: Invoking rez_avatar on host:{0} for avatar: {1} {2}", rezAvatarString, userState.first_name, userState.last_name); + + OSDMap rezResponseMap = invokeRezAvatarCap(responseMap, rezAvatarString,userState); + + // If invoking it returned an error, parse and end + if (rezResponseMap.ContainsKey("connect")) + { + if (rezResponseMap["connect"].AsBoolean() == false) + { + return responseMap; + } + } + + string rezRespSeedCap = ""; + + // DEPRECIATED + if (rezResponseMap.ContainsKey("seed_capability")) + rezRespSeedCap = rezResponseMap["seed_capability"].AsString(); + + // REPLACEMENT + if (rezResponseMap.ContainsKey("region_seed_capability")) + rezRespSeedCap = rezResponseMap["region_seed_capability"].AsString(); + + // REPLACEMENT + if (rezResponseMap.ContainsKey("rez_avatar/rez")) + rezRespSeedCap = rezResponseMap["rez_avatar/rez"].AsString(); + + // DEPRECIATED + string rezRespSim_ip = rezResponseMap["sim_ip"].AsString(); + + string rezRespSim_host = rezResponseMap["sim_host"].AsString(); + + int rrPort = rezResponseMap["sim_port"].AsInteger(); + int rrX = rezResponseMap["region_x"].AsInteger(); + int rrY = rezResponseMap["region_y"].AsInteger(); + m_log.ErrorFormat("X:{0}, Y:{1}", rrX, rrY); + UUID rrRID = rezResponseMap["region_id"].AsUUID(); + OSDArray RezResponsePositionArray = null; + string rrAccess = rezResponseMap["sim_access"].AsString(); + if (rezResponseMap.ContainsKey("position")) + { + RezResponsePositionArray = (OSDArray)rezResponseMap["position"]; + } + // DEPRECIATED + responseMap["seed_capability"] = OSD.FromString(rezRespSeedCap); + + // REPLACEMENT r3 + responseMap["region_seed_capability"] = OSD.FromString(rezRespSeedCap); + + // DEPRECIATED + responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(rezRespSim_ip).ToString()); + + responseMap["sim_host"] = OSD.FromString(rezRespSim_host); + responseMap["sim_port"] = OSD.FromInteger(rrPort); + responseMap["region_x"] = OSD.FromInteger(rrX ); + responseMap["region_y"] = OSD.FromInteger(rrY ); + responseMap["region_id"] = OSD.FromUUID(rrRID); + responseMap["sim_access"] = OSD.FromString(rrAccess); + + if (RezResponsePositionArray != null) + { + responseMap["position"] = RezResponsePositionArray; + } + responseMap["look_at"] = lookArray; + responseMap["connect"] = OSD.FromBoolean(true); + + ShutdownConnection(LocalID,this); + // PLEASE STOP CHANGING THIS TO an M_LOG, M_LOG DOESN'T WORK ON MULTILINE .TOSTRINGS + System.Console.WriteLine("RESPONSEDEREZ: " + responseMap.ToString()); + return responseMap; + } + else + { + return GenerateNoStateMessage(LocalID); + } + } + else + { + return GenerateNoHandlerMessage(); + } + + //return responseMap; + } + + private OSDMap invokeRezAvatarCap(OSDMap responseMap, string CapAddress, OGPState userState) + { + Scene reg = GetRootScene(); + + WebRequest DeRezRequest = WebRequest.Create(CapAddress); + DeRezRequest.Method = "POST"; + DeRezRequest.ContentType = "application/xml+llsd"; + + OSDMap RAMap = new OSDMap(); + OSDMap AgentParms = new OSDMap(); + OSDMap RegionParms = new OSDMap(); + + OSDArray Parameter = new OSDArray(2); + + OSDMap version = new OSDMap(); + version["version"] = OSD.FromInteger(userState.src_version); + Parameter.Add(version); + + OSDMap SrcData = new OSDMap(); + SrcData["estate_id"] = OSD.FromInteger(reg.RegionInfo.EstateSettings.EstateID); + SrcData["parent_estate_id"] = OSD.FromInteger((reg.RegionInfo.EstateSettings.ParentEstateID == 100 ? 1 : reg.RegionInfo.EstateSettings.ParentEstateID)); + SrcData["region_id"] = OSD.FromUUID(reg.RegionInfo.originRegionID); + SrcData["visible_to_parent"] = OSD.FromBoolean(userState.visible_to_parent); + Parameter.Add(SrcData); + + AgentParms["first_name"] = OSD.FromString(userState.first_name); + AgentParms["last_name"] = OSD.FromString(userState.last_name); + AgentParms["agent_id"] = OSD.FromUUID(userState.agent_id); + RegionParms["region_id"] = OSD.FromUUID(userState.region_id); + AgentParms["circuit_code"] = OSD.FromInteger(userState.circuit_code); + AgentParms["secure_session_id"] = OSD.FromUUID(userState.secure_session_id); + AgentParms["session_id"] = OSD.FromUUID(userState.session_id); + AgentParms["agent_access"] = OSD.FromBoolean(userState.agent_access); + AgentParms["god_level"] = OSD.FromInteger(userState.god_level); + AgentParms["god_overide"] = OSD.FromBoolean(userState.god_overide); + AgentParms["identified"] = OSD.FromBoolean(userState.identified); + AgentParms["transacted"] = OSD.FromBoolean(userState.transacted); + AgentParms["age_verified"] = OSD.FromBoolean(userState.age_verified); + AgentParms["limited_to_estate"] = OSD.FromInteger(userState.limited_to_estate); + AgentParms["inventory_host"] = OSD.FromString(userState.inventory_host); + + // version 1 + RAMap = AgentParms; + + // Planned for version 2 + // RAMap["agent_params"] = AgentParms; + + RAMap["region_params"] = RegionParms; + RAMap["parameter"] = Parameter; + + string RAMapString = RAMap.ToString(); + m_log.InfoFormat("[OGP] RAMap string {0}", RAMapString); + OSD LLSDofRAMap = RAMap; // RENAME if this works + + m_log.InfoFormat("[OGP]: LLSD of map as string was {0}", LLSDofRAMap.ToString()); + //m_log.InfoFormat("[OGP]: LLSD+XML: {0}", LLSDParser.SerializeXmlString(LLSDofRAMap)); + byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); + + //string bufferDump = System.Text.Encoding.ASCII.GetString(buffer); + //m_log.InfoFormat("[OGP]: buffer form is {0}",bufferDump); + //m_log.InfoFormat("[OGP]: LLSD of map was {0}",buffer.Length); + + Stream os = null; + try + { // send the Post + DeRezRequest.ContentLength = buffer.Length; //Count bytes to send + os = DeRezRequest.GetRequestStream(); + os.Write(buffer, 0, buffer.Length); //Send it + os.Close(); + m_log.InfoFormat("[OGP]: Derez Avatar Posted Rez Avatar request to remote sim {0}", CapAddress); + } + catch (WebException ex) + { + m_log.InfoFormat("[OGP] Bad send on de_rez_avatar {0}", ex.Message); + responseMap["connect"] = OSD.FromBoolean(false); + + return responseMap; + } + + m_log.Info("[OGP] waiting for a reply after rez avatar send"); + string rez_avatar_reply = null; + { // get the response + try + { + WebResponse webResponse = DeRezRequest.GetResponse(); + if (webResponse == null) + { + m_log.Info("[OGP:] Null reply on rez_avatar post"); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + rez_avatar_reply = sr.ReadToEnd().Trim(); + m_log.InfoFormat("[OGP]: rez_avatar reply was {0} ", rez_avatar_reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[OGP]: exception on read after send of rez avatar {0}", ex.Message); + responseMap["connect"] = OSD.FromBoolean(false); + + return responseMap; + } + OSD rezResponse = null; + try + { + rezResponse = OSDParser.DeserializeLLSDXml(rez_avatar_reply); + + responseMap = (OSDMap)rezResponse; + } + catch (Exception ex) + { + m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message); + responseMap["connect"] = OSD.FromBoolean(false); + + return responseMap; + } + } + return responseMap; + } + + public OSD GenerateNoHandlerMessage() + { + OSDMap map = new OSDMap(); + map["reason"] = OSD.FromString("LLSDRequest"); + map["message"] = OSD.FromString("No handler registered for LLSD Requests"); + map["login"] = OSD.FromString("false"); + map["connect"] = OSD.FromString("false"); + return map; + } + public OSD GenerateNoStateMessage(UUID passedAvatar) + { + OSDMap map = new OSDMap(); + map["reason"] = OSD.FromString("derez failed"); + map["message"] = OSD.FromString("Unable to locate OGP state for avatar " + passedAvatar.ToString()); + map["login"] = OSD.FromString("false"); + map["connect"] = OSD.FromString("false"); + return map; + } + private bool TryGetAgentCircuitData(string path, out AgentCircuitData userdata) + { + userdata = null; + lock (CapsLoginID) + { + if (CapsLoginID.ContainsKey(path)) + { + userdata = CapsLoginID[path]; + DiscardUsedCap(path); + return true; + } + } + return false; + } + + private void DiscardUsedCap(string path) + { + CapsLoginID.Remove(path); + } + + private Scene GetRootScene() + { + Scene ReturnScene = null; + lock (m_scene) + { + if (m_scene.Count > 0) + { + ReturnScene = m_scene[0]; + } + } + + return ReturnScene; + } + + private Scene GetScene(string scenename) + { + Scene ReturnScene = null; + lock (m_scene) + { + foreach (Scene s in m_scene) + { + if (s.RegionInfo.RegionName.ToLower() == scenename) + { + ReturnScene = s; + break; + } + } + } + + return ReturnScene; + } + + private ulong GetOSCompatibleRegionHandle(RegionInfo reg) + { + return Util.UIntsToLong(reg.RegionLocX, reg.RegionLocY); + } + + private OGPState InitializeNewState() + { + OGPState returnState = new OGPState(); + returnState.first_name = ""; + returnState.last_name = ""; + returnState.agent_id = UUID.Zero; + returnState.local_agent_id = UUID.Zero; + returnState.region_id = UUID.Zero; + returnState.circuit_code = 0; + returnState.secure_session_id = UUID.Zero; + returnState.session_id = UUID.Zero; + returnState.agent_access = true; + returnState.god_level = 0; + returnState.god_overide = false; + returnState.identified = false; + returnState.transacted = false; + returnState.age_verified = false; + returnState.limited_to_estate = 1; + returnState.inventory_host = "http://inv4.mysql.aditi.lindenlab.com"; + returnState.allow_redirect = true; + returnState.sim_access = ""; + returnState.src_can_see_mainland = true; + returnState.src_estate_id = 1; + returnState.src_version = 1; + returnState.src_parent_estate_id = 1; + returnState.visible_to_parent = true; + returnState.teleported_into_region = ""; + + return returnState; + } + + private OGPState GetOGPState(UUID agentId) + { + lock (m_OGPState) + { + if (m_OGPState.ContainsKey(agentId)) + { + return m_OGPState[agentId]; + } + else + { + return InitializeNewState(); + } + } + } + + public void DeleteOGPState(UUID agentId) + { + lock (m_OGPState) + { + if (m_OGPState.ContainsKey(agentId)) + m_OGPState.Remove(agentId); + } + } + + private void UpdateOGPState(UUID agentId, OGPState state) + { + lock (m_OGPState) + { + if (m_OGPState.ContainsKey(agentId)) + { + m_OGPState[agentId] = state; + } + else + { + m_OGPState.Add(agentId,state); + } + } + } + private bool SceneListDuplicateCheck(string str) + { + // no lock, called from locked space! + bool found = false; + + foreach (Scene s in m_scene) + { + if (s.RegionInfo.RegionName == str) + { + found = true; + break; + } + } + + return found; + } + + public void ShutdownConnection(UUID avatarId, OpenGridProtocolModule mod) + { + Scene homeScene = GetRootScene(); + ScenePresence avatar = null; + if (homeScene.TryGetAvatar(avatarId,out avatar)) + { + KillAUser ku = new KillAUser(avatar,mod); + Thread ta = new Thread(ku.ShutdownNoLogout); + ta.IsBackground = true; + ta.Name = "ShutdownThread"; + ta.Start(); + } + } + + private string CreateRandomStr(int len) + { + Random rnd = new Random(System.Environment.TickCount); + string returnstring = ""; + string chars = "abcdefghijklmnopqrstuvwxyz0123456789"; + + for (int i = 0; i < len; i++) + { + returnstring += chars.Substring(rnd.Next(chars.Length), 1); + } + return returnstring; + } + // Temporary hack to allow teleporting to and from Vaak + private static bool customXertificateValidation(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) + { + //if (cert.Subject == "E=root@lindenlab.com, CN=*.vaak.lindenlab.com, O=\"Linden Lab, Inc.\", L=San Francisco, S=California, C=US") + //{ + return true; + //} + + //return false; + } + } + + public class KillAUser + { + private ScenePresence avToBeKilled = null; + private OpenGridProtocolModule m_mod = null; + + public KillAUser(ScenePresence avatar, OpenGridProtocolModule mod) + { + avToBeKilled = avatar; + m_mod = mod; + } + + public void ShutdownNoLogout() + { + UUID avUUID = UUID.Zero; + + if (avToBeKilled != null) + { + avUUID = avToBeKilled.UUID; + avToBeKilled.MakeChildAgent(); + + avToBeKilled.ControllingClient.SendLogoutPacketWhenClosing = false; + + Thread.Sleep(30000); + + // test for child agent because they might have come back + if (avToBeKilled.IsChildAgent) + { + m_mod.DeleteOGPState(avUUID); + avToBeKilled.ControllingClient.Close(true); + } + } + } + + } + + public class MonoCert : ICertificatePolicy + { + #region ICertificatePolicy Members + + public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) + { + return true; + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs new file mode 100644 index 0000000..e6a12a4 --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -0,0 +1,332 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using OpenMetaverse; +using OpenMetaverse.Imaging; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture +{ + public class DynamicTextureModule : IRegionModule, IDynamicTextureManager + { + private Dictionary RegisteredScenes = new Dictionary(); + + private Dictionary RenderPlugins = + new Dictionary(); + + private Dictionary Updaters = new Dictionary(); + + #region IDynamicTextureManager Members + + public void RegisterRender(string handleType, IDynamicTextureRender render) + { + if (!RenderPlugins.ContainsKey(handleType)) + { + RenderPlugins.Add(handleType, render); + } + } + + /// + /// Called by code which actually renders the dynamic texture to supply texture data. + /// + /// + /// + public void ReturnData(UUID id, byte[] data) + { + if (Updaters.ContainsKey(id)) + { + DynamicTextureUpdater updater = Updaters[id]; + if (RegisteredScenes.ContainsKey(updater.SimUUID)) + { + Scene scene = RegisteredScenes[updater.SimUUID]; + updater.DataReceived(data, scene); + } + } + } + + public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, + string extraParams, int updateTimer) + { + return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); + } + + public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, + string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + { + if (RenderPlugins.ContainsKey(contentType)) + { + //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType); + + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.Url = url; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = UUID.Random(); + updater.Params = extraParams; + updater.BlendWithOldTexture = SetBlending; + updater.FrontAlpha = AlphaValue; + + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + + RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); + return updater.UpdaterID; + } + return UUID.Zero; + } + + public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, + string extraParams, int updateTimer) + { + return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); + } + + public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, + string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + { + if (RenderPlugins.ContainsKey(contentType)) + { + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.BodyData = data; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = UUID.Random(); + updater.Params = extraParams; + updater.BlendWithOldTexture = SetBlending; + updater.FrontAlpha = AlphaValue; + + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + + RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); + return updater.UpdaterID; + } + return UUID.Zero; + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) + { + RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); + scene.RegisterModuleInterface(this); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "DynamicTextureModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region Nested type: DynamicTextureUpdater + + public class DynamicTextureUpdater + { + public bool BlendWithOldTexture = false; + public string BodyData; + public string ContentType; + public byte FrontAlpha = 255; + public UUID LastAssetID; + public string Params; + public UUID PrimID; + public bool SetNewFrontAlpha = false; + public UUID SimUUID; + public UUID UpdaterID; + public int UpdateTimer; + public string Url; + + public DynamicTextureUpdater() + { + LastAssetID = UUID.Zero; + UpdateTimer = 0; + BodyData = null; + } + + /// + /// Called once new texture data has been received for this updater. + /// + public void DataReceived(byte[] data, Scene scene) + { + SceneObjectPart part = scene.GetSceneObjectPart(PrimID); + byte[] assetData; + AssetBase oldAsset = null; + + if (BlendWithOldTexture) + { + UUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID; + oldAsset = scene.AssetCache.GetAsset(lastTextureID, true); + if (oldAsset != null) + { + assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); + } + else + { + assetData = new byte[data.Length]; + Array.Copy(data, assetData, data.Length); + } + } + else + { + assetData = new byte[data.Length]; + Array.Copy(data, assetData, data.Length); + } + + // Create a new asset for user + AssetBase asset = new AssetBase(); + asset.Metadata.FullID = UUID.Random(); + asset.Data = assetData; + asset.Metadata.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); + asset.Metadata.Type = 0; + asset.Metadata.Description = "dynamic image"; + asset.Metadata.Local = false; + asset.Metadata.Temporary = true; + scene.AssetCache.AddAsset(asset); + + LastAssetID = asset.Metadata.FullID; + + IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface(); + if (cacheLayerDecode != null) + { + cacheLayerDecode.syncdecode(asset.Metadata.FullID, asset.Data); + } + cacheLayerDecode = null; + + // mostly keep the values from before + Primitive.TextureEntry tmptex = part.Shape.Textures; + + // remove the old asset from the cache + UUID oldID = tmptex.DefaultTexture.TextureID; + scene.AssetCache.ExpireAsset(oldID); + + tmptex.DefaultTexture.TextureID = asset.Metadata.FullID; + // I'm pretty sure we always want to force this to true + tmptex.DefaultTexture.Fullbright = true; + + part.Shape.Textures = tmptex; + part.ScheduleFullUpdate(); + } + + private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) + { + ManagedImage managedImage; + Image image; + + if (OpenJPEG.DecodeToImage(frontImage, out managedImage, out image)) + { + Bitmap image1 = new Bitmap(image); + + if (OpenJPEG.DecodeToImage(backImage, out managedImage, out image)) + { + Bitmap image2 = new Bitmap(image); + + if (setNewAlpha) + SetAlpha(ref image1, newAlpha); + + Bitmap joint = MergeBitMaps(image1, image2); + + byte[] result = new byte[0]; + + try + { + result = OpenJPEG.EncodeFromImage(joint, true); + } + catch (Exception) + { + Console.WriteLine( + "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); + } + + return result; + } + } + + return null; + } + + public Bitmap MergeBitMaps(Bitmap front, Bitmap back) + { + Bitmap joint; + Graphics jG; + + joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb); + jG = Graphics.FromImage(joint); + + jG.DrawImage(back, 0, 0, back.Width, back.Height); + jG.DrawImage(front, 0, 0, back.Width, back.Height); + + return joint; + } + + private void SetAlpha(ref Bitmap b, byte alpha) + { + for (int w = 0; w < b.Width; w++) + { + for (int h = 0; h < b.Height; h++) + { + b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h))); + } + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs new file mode 100644 index 0000000..c23ff1e --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -0,0 +1,288 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using log4net; +using Nini.Config; +using DotNetOpenMail; +using DotNetOpenMail.SmtpAuth; + +namespace OpenSim.Region.CoreModules.Scripting.EmailModules +{ + public class EmailModule : IEmailModule + { + // + // Log + // + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // + // Module vars + // + private IConfigSource m_Config; + private string m_HostName = string.Empty; + //private string m_RegionName = string.Empty; + private string SMTP_SERVER_HOSTNAME = string.Empty; + private int SMTP_SERVER_PORT = 25; + private string SMTP_SERVER_LOGIN = string.Empty; + private string SMTP_SERVER_PASSWORD = string.Empty; + + // Scenes by Region Handle + private Dictionary m_Scenes = + new Dictionary(); + + private bool m_Enabled = false; + + public void Initialise(Scene scene, IConfigSource config) + { + m_Config = config; + IConfig SMTPConfig; + + //FIXME: RegionName is correct?? + //m_RegionName = scene.RegionInfo.RegionName; + + IConfig startupConfig = m_Config.Configs["Startup"]; + + m_Enabled = (startupConfig.GetString("emailmodule", "DefaultEmailModule") == "DefaultEmailModule"); + + //Load SMTP SERVER config + try + { + if ((SMTPConfig = m_Config.Configs["SMTP"]) == null) + { + m_log.InfoFormat("[SMTP] SMTP server not configured"); + m_Enabled = false; + return; + } + + if (!SMTPConfig.GetBoolean("enabled", false)) + { + m_log.InfoFormat("[SMTP] module disabled in configuration"); + m_Enabled = false; + return; + } + + m_HostName = SMTPConfig.GetString("host_domain_header_from", m_HostName); + SMTP_SERVER_HOSTNAME = SMTPConfig.GetString("SMTP_SERVER_HOSTNAME",SMTP_SERVER_HOSTNAME); + SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT); + SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN); + SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD); + } + catch (Exception e) + { + m_log.Error("[EMAIL] DefaultEmailModule not configured: "+ e.Message); + m_Enabled = false; + return; + } + + // It's a go! + if (m_Enabled) + { + lock (m_Scenes) + { + // Claim the interface slot + scene.RegisterModuleInterface(this); + + // Add to scene list + if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle)) + { + m_Scenes[scene.RegionInfo.RegionHandle] = scene; + } + else + { + m_Scenes.Add(scene.RegionInfo.RegionHandle, scene); + } + } + + m_log.Info("[EMAIL] Activated DefaultEmailModule"); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "DefaultEmailModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + /// + /// + /// + /// + private void DelayInSeconds(int seconds) + { + TimeSpan DiffDelay = new TimeSpan(0, 0, seconds); + DateTime EndDelay = DateTime.Now.Add(DiffDelay); + while (DateTime.Now < EndDelay) + { + ;//Do nothing!! + } + } + + private SceneObjectPart findPrim(UUID objectID, out string ObjectRegionName) + { + lock (m_Scenes) + { + foreach (Scene s in m_Scenes.Values) + { + SceneObjectPart part = s.GetSceneObjectPart(objectID); + if (part != null) + { + ObjectRegionName = s.RegionInfo.RegionName; + return part; + } + } + } + ObjectRegionName = string.Empty; + return null; + } + + private void resolveNamePositionRegionName(UUID objectID, out string ObjectName, out string ObjectAbsolutePosition, out string ObjectRegionName) + { + string m_ObjectRegionName; + SceneObjectPart part = findPrim(objectID, out m_ObjectRegionName); + if (part != null) + { + ObjectAbsolutePosition = part.AbsolutePosition.ToString(); + ObjectName = part.Name; + ObjectRegionName = m_ObjectRegionName; + return; + } + ObjectAbsolutePosition = part.AbsolutePosition.ToString(); + ObjectName = part.Name; + ObjectRegionName = m_ObjectRegionName; + return; + } + + /// + /// SendMail function utilized by llEMail + /// + /// + /// + /// + /// + public void SendEmail(UUID objectID, string address, string subject, string body) + { + //Check if address is empty + if (address == string.Empty) + return; + + //FIXED:Check the email is correct form in REGEX + string EMailpatternStrict = @"^(([^<>()[\]\\.,;:\s@\""]+" + + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@" + + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" + + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+" + + @"[a-zA-Z]{2,}))$"; + Regex EMailreStrict = new Regex(EMailpatternStrict); + bool isEMailStrictMatch = EMailreStrict.IsMatch(address); + if (!isEMailStrictMatch) + { + m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); + return; + } + //FIXME:Check if subject + body = 4096 Byte + if ((subject.Length + body.Length) > 1024) + { + m_log.Error("[EMAIL] subject + body > 1024 Byte"); + return; + } + + try + { + string LastObjectName = string.Empty; + string LastObjectPosition = string.Empty; + string LastObjectRegionName = string.Empty; + //DONE: Message as Second Life style + //20 second delay - AntiSpam System - for now only 10 seconds + DelayInSeconds(10); + //Creation EmailMessage + EmailMessage emailMessage = new EmailMessage(); + //From + emailMessage.FromAddress = new EmailAddress(objectID.ToString()+"@"+m_HostName); + //To - Only One + emailMessage.AddToAddress(new EmailAddress(address)); + //Subject + emailMessage.Subject = subject; + //TEXT Body + resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); + emailMessage.TextPart = new TextAttachment("Object-Name: " + LastObjectName + + "\r\nRegion: " + LastObjectRegionName + "\r\nLocal-Position: " + + LastObjectPosition+"\r\n\r\n\r\n" + body); + //HTML Body + emailMessage.HtmlPart = new HtmlAttachment("

" + + "
Object-Name: " + LastObjectName + + "
Region: " + LastObjectRegionName + + "
Local-Position: " + LastObjectPosition + "


" + +body+"\r\n

"); + + //Set SMTP SERVER config + SmtpServer smtpServer=new SmtpServer(SMTP_SERVER_HOSTNAME,SMTP_SERVER_PORT); + //Authentication + smtpServer.SmtpAuthToken=new SmtpAuthToken(SMTP_SERVER_LOGIN, SMTP_SERVER_PASSWORD); + //Send Email Message + emailMessage.Send(smtpServer); + //Log + m_log.Info("[EMAIL] EMail sent to: " + address + " from object: " + objectID.ToString()); + } + catch (Exception e) + { + m_log.Error("[EMAIL] DefaultEmailModule Exception: "+e.Message); + return; + } + } + + /// + /// + /// + /// + /// + /// + /// + public Email GetNextEmail(UUID objectID, string sender, string subject) + { + return null; + } + } +} diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs new file mode 100644 index 0000000..9f3bd09 --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -0,0 +1,437 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using OpenMetaverse; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using System.Collections; + +/***************************************************** + * + * ScriptsHttpRequests + * + * Implements the llHttpRequest and http_response + * callback. + * + * Some stuff was already in LSLLongCmdHandler, and then + * there was this file with a stub class in it. So, + * I am moving some of the objects and functions out of + * LSLLongCmdHandler, such as the HttpRequestClass, the + * start and stop methods, and setting up pending and + * completed queues. These are processed in the + * LSLLongCmdHandler polling loop. Similiar to the + * XMLRPCModule, since that seems to work. + * + * //TODO + * + * This probably needs some throttling mechanism but + * it's wide open right now. This applies to both + * number of requests and data volume. + * + * Linden puts all kinds of header fields in the requests. + * Not doing any of that: + * User-Agent + * X-SecondLife-Shard + * X-SecondLife-Object-Name + * X-SecondLife-Object-Key + * X-SecondLife-Region + * X-SecondLife-Local-Position + * X-SecondLife-Local-Velocity + * X-SecondLife-Local-Rotation + * X-SecondLife-Owner-Name + * X-SecondLife-Owner-Key + * + * HTTPS support + * + * Configurable timeout? + * Configurable max response size? + * Configurable + * + * **************************************************/ + +namespace OpenSim.Region.CoreModules.Scripting.HttpRequest +{ + public class HttpRequestModule : IRegionModule, IHttpRequestModule + { + private object HttpListLock = new object(); + private int httpTimeout = 30000; + private string m_name = "HttpScriptRequests"; + + private string m_proxyurl = ""; + private string m_proxyexcepts = ""; + + // + private Dictionary m_pendingRequests; + private Scene m_scene; + // private Queue rpcQueue = new Queue(); + + public HttpRequestModule() + { + } + + #region IHttpRequestModule Members + + public UUID MakeHttpRequest(string url, string parameters, string body) + { + return UUID.Zero; + } + + public UUID StartHttpRequest(uint localID, UUID itemID, string url, List parameters, Dictionary headers, string body) + { + UUID reqID = UUID.Random(); + HttpRequestClass htc = new HttpRequestClass(); + + // Partial implementation: support for parameter flags needed + // see http://wiki.secondlife.com/wiki/LlHTTPRequest + // + // Parameters are expected in {key, value, ... , key, value} + if (parameters != null) + { + string[] parms = parameters.ToArray(); + for (int i = 0; i < parms.Length; i += 2) + { + switch (Int32.Parse(parms[i])) + { + case (int)HttpRequestConstants.HTTP_METHOD: + + htc.HttpMethod = parms[i + 1]; + break; + + case (int)HttpRequestConstants.HTTP_MIMETYPE: + + htc.HttpMIMEType = parms[i + 1]; + break; + + case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH: + + // TODO implement me + break; + + case (int)HttpRequestConstants.HTTP_VERIFY_CERT: + + // TODO implement me + break; + } + } + } + + htc.LocalID = localID; + htc.ItemID = itemID; + htc.Url = url; + htc.ReqID = reqID; + htc.HttpTimeout = httpTimeout; + htc.OutboundBody = body; + htc.ResponseHeaders = headers; + htc.proxyurl = m_proxyurl; + htc.proxyexcepts = m_proxyexcepts; + + lock (HttpListLock) + { + m_pendingRequests.Add(reqID, htc); + } + + htc.Process(); + + return reqID; + } + + public void StopHttpRequest(uint m_localID, UUID m_itemID) + { + if (m_pendingRequests != null) + { + lock (HttpListLock) + { + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) + { + tmpReq.Stop(); + m_pendingRequests.Remove(m_itemID); + } + } + } + } + + /* + * TODO + * Not sure how important ordering is is here - the next first + * one completed in the list is returned, based soley on its list + * position, not the order in which the request was started or + * finsihed. I thought about setting up a queue for this, but + * it will need some refactoring and this works 'enough' right now + */ + + public IServiceRequest GetNextCompletedRequest() + { + lock (HttpListLock) + { + foreach (UUID luid in m_pendingRequests.Keys) + { + HttpRequestClass tmpReq; + + if (m_pendingRequests.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.Finished) + { + return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedRequest(UUID id) + { + lock (HttpListLock) + { + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(id, out tmpReq)) + { + tmpReq.Stop(); + tmpReq = null; + m_pendingRequests.Remove(id); + } + } + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + + m_scene.RegisterModuleInterface(this); + + m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); + m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); + + m_pendingRequests = new Dictionary(); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + } + + public class HttpRequestClass: IServiceRequest + { + // Constants for parameters + // public const int HTTP_BODY_MAXLENGTH = 2; + // public const int HTTP_METHOD = 0; + // public const int HTTP_MIMETYPE = 1; + // public const int HTTP_VERIFY_CERT = 3; + private bool _finished; + public bool Finished + { + get { return _finished; } + } + // public int HttpBodyMaxLen = 2048; // not implemented + + // Parameter members and default values + public string HttpMethod = "GET"; + public string HttpMIMEType = "text/plain;charset=utf-8"; + public int HttpTimeout; + // public bool HttpVerifyCert = true; // not implemented + private Thread httpThread; + + // Request info + private UUID _itemID; + public UUID ItemID + { + get { return _itemID; } + set { _itemID = value; } + } + private uint _localID; + public uint LocalID + { + get { return _localID; } + set { _localID = value; } + } + public DateTime Next; + public string proxyurl; + public string proxyexcepts; + public string OutboundBody; + private UUID _reqID; + public UUID ReqID + { + get { return _reqID; } + set { _reqID = value; } + } + public HttpWebRequest Request; + public string ResponseBody; + public List ResponseMetadata; + public Dictionary ResponseHeaders; + public int Status; + public string Url; + + public void Process() + { + httpThread = new Thread(SendRequest); + httpThread.Name = "HttpRequestThread"; + httpThread.Priority = ThreadPriority.BelowNormal; + httpThread.IsBackground = true; + _finished = false; + httpThread.Start(); + ThreadTracker.Add(httpThread); + } + + /* + * TODO: More work on the response codes. Right now + * returning 200 for success or 499 for exception + */ + + public void SendRequest() + { + HttpWebResponse response = null; + StringBuilder sb = new StringBuilder(); + byte[] buf = new byte[8192]; + string tempString = null; + int count = 0; + + try + { + Request = (HttpWebRequest) WebRequest.Create(Url); + Request.Method = HttpMethod; + Request.ContentType = HttpMIMEType; + + if (proxyurl != null && proxyurl.Length > 0) + { + if (proxyexcepts != null && proxyexcepts.Length > 0) + { + string[] elist = proxyexcepts.Split(';'); + Request.Proxy = new WebProxy(proxyurl, true, elist); + } + else + { + Request.Proxy = new WebProxy(proxyurl, true); + } + } + + foreach (KeyValuePair entry in ResponseHeaders) + Request.Headers[entry.Key] = entry.Value; + + // Encode outbound data + if (OutboundBody.Length > 0) + { + byte[] data = Encoding.UTF8.GetBytes(OutboundBody); + + Request.ContentLength = data.Length; + Stream bstream = Request.GetRequestStream(); + bstream.Write(data, 0, data.Length); + bstream.Close(); + } + + Request.Timeout = HttpTimeout; + // execute the request + response = (HttpWebResponse) Request.GetResponse(); + + Stream resStream = response.GetResponseStream(); + + do + { + // fill the buffer with data + count = resStream.Read(buf, 0, buf.Length); + + // make sure we read some data + if (count != 0) + { + // translate from bytes to ASCII text + tempString = Encoding.UTF8.GetString(buf, 0, count); + + // continue building the string + sb.Append(tempString); + } + } while (count > 0); // any more data to read? + + ResponseBody = sb.ToString(); + } + catch (Exception e) + { + if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError) + { + HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; + Status = (int)webRsp.StatusCode; + ResponseBody = webRsp.StatusDescription; + } + else + { + Status = (int)OSHttpStatusCode.ClientErrorJoker; + ResponseBody = e.Message; + } + + _finished = true; + return; + } + finally + { + if (response != null) + response.Close(); + } + + Status = (int)OSHttpStatusCode.SuccessOk; + _finished = true; + } + + public void Stop() + { + try + { + httpThread.Abort(); + } + catch (Exception) + { + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs new file mode 100644 index 0000000..afcaff1 --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -0,0 +1,229 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Drawing; +using System.IO; +using System.Net; +using OpenMetaverse; +using OpenMetaverse.Imaging; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL +{ + public class LoadImageURLModule : IRegionModule, IDynamicTextureRender + { + private string m_name = "LoadImageURL"; + private Scene m_scene; + private IDynamicTextureManager m_textureManager; + + private string m_proxyurl = ""; + private string m_proxyexcepts = ""; + + #region IDynamicTextureRender Members + + public string GetName() + { + return m_name; + } + + public string GetContentType() + { + return ("image"); + } + + public bool SupportsAsynchronous() + { + return true; + } + + public byte[] ConvertUrl(string url, string extraParams) + { + return null; + } + + public byte[] ConvertStream(Stream data, string extraParams) + { + return null; + } + + public bool AsyncConvertUrl(UUID id, string url, string extraParams) + { + MakeHttpRequest(url, id); + return true; + } + + public bool AsyncConvertData(UUID id, string bodyData, string extraParams) + { + return false; + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + m_scene = scene; + } + + m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); + m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); + } + + public void PostInitialise() + { + m_textureManager = m_scene.RequestModuleInterface(); + if (m_textureManager != null) + { + m_textureManager.RegisterRender(GetContentType(), this); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void MakeHttpRequest(string url, UUID requestID) + { + WebRequest request = HttpWebRequest.Create(url); + + if (m_proxyurl != null && m_proxyurl.Length > 0) + { + if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) + { + string[] elist = m_proxyexcepts.Split(';'); + request.Proxy = new WebProxy(m_proxyurl, true, elist); + } + else + { + request.Proxy = new WebProxy(m_proxyurl, true); + } + } + + RequestState state = new RequestState((HttpWebRequest) request, requestID); + // IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); + request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); + + TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1)); + state.TimeOfRequest = (int) t.TotalSeconds; + } + + private void HttpRequestReturn(IAsyncResult result) + { + RequestState state = (RequestState) result.AsyncState; + WebRequest request = (WebRequest) state.Request; + try + { + HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); + if (response.StatusCode == HttpStatusCode.OK) + { + Bitmap image = new Bitmap(response.GetResponseStream()); + Size newsize; + + // TODO: make this a bit less hard coded + if ((image.Height < 64) && (image.Width < 64)) + { + newsize = new Size(32, 32); + } + else if ((image.Height < 128) && (image.Width < 128)) + { + newsize = new Size(64, 64); + } + else if ((image.Height < 256) && (image.Width < 256)) + { + newsize = new Size(128, 128); + } + else if ((image.Height < 512 && image.Width < 512)) + { + newsize = new Size(256, 256); + } + else if ((image.Height < 1024 && image.Width < 1024)) + { + newsize = new Size(512, 512); + } + else + { + newsize = new Size(1024, 1024); + } + + Bitmap resize = new Bitmap(image, newsize); + byte[] imageJ2000 = new byte[0]; + + try + { + imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); + } + catch (Exception) + { + Console.WriteLine( + "[LOADIMAGEURLMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); + } + + m_textureManager.ReturnData(state.RequestID, imageJ2000); + } + } + catch (WebException) + { + + } + } + + #region Nested type: RequestState + + public class RequestState + { + public HttpWebRequest Request = null; + public UUID RequestID = UUID.Zero; + public int TimeOfRequest = 0; + + public RequestState(HttpWebRequest request, UUID requestID) + { + Request = request; + RequestID = requestID; + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs new file mode 100644 index 0000000..0c709b5 --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -0,0 +1,515 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Globalization; +using System.IO; +using System.Net; +using OpenMetaverse; +using OpenMetaverse.Imaging; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +//using Cairo; + +namespace OpenSim.Region.CoreModules.Scripting.VectorRender +{ + public class VectorRenderModule : IRegionModule, IDynamicTextureRender + { + private string m_name = "VectorRenderModule"; + private Scene m_scene; + private IDynamicTextureManager m_textureManager; + + public VectorRenderModule() + { + } + + #region IDynamicTextureRender Members + + public string GetContentType() + { + return ("vector"); + } + + public string GetName() + { + return m_name; + } + + public bool SupportsAsynchronous() + { + return true; + } + + public byte[] ConvertUrl(string url, string extraParams) + { + return null; + } + + public byte[] ConvertStream(Stream data, string extraParams) + { + return null; + } + + public bool AsyncConvertUrl(UUID id, string url, string extraParams) + { + return false; + } + + public bool AsyncConvertData(UUID id, string bodyData, string extraParams) + { + Draw(bodyData, id, extraParams); + return true; + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + m_scene = scene; + } + } + + public void PostInitialise() + { + m_textureManager = m_scene.RequestModuleInterface(); + if (m_textureManager != null) + { + m_textureManager.RegisterRender(GetContentType(), this); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void Draw(string data, UUID id, string extraParams) + { + // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha + // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 + int width = 256; + int height = 256; + int alpha = 255; // 0 is transparent + + char[] paramDelimiter = { ',' }; + char[] nvpDelimiter = { ':' }; + + extraParams = extraParams.Trim(); + extraParams = extraParams.ToLower(); + + string[] nvps = extraParams.Split(paramDelimiter); + + int temp = -1; + foreach (string pair in nvps) + { + string[] nvp = pair.Split(nvpDelimiter); + string name = ""; + string value = ""; + + if (nvp[0] != null) + { + name = nvp[0].Trim(); + } + + if (nvp.Length == 2) + { + value = nvp[1].Trim(); + } + + switch (name) + { + case "width": + temp = parseIntParam(value); + if (temp != -1) + { + if (temp < 1) + { + width = 1; + } + else if (temp > 2048) + { + width = 2048; + } + else + { + width = temp; + } + } + break; + case "height": + temp = parseIntParam(value); + if (temp != -1) + { + if (temp < 1) + { + height = 1; + } + else if (temp > 2048) + { + height = 2048; + } + else + { + height = temp; + } + } + break; + case "alpha": + temp = parseIntParam(value); + if (temp != -1) + { + if (temp < 0) + { + alpha = 0; + } + else if (temp > 255) + { + alpha = 255; + } + else + { + alpha = temp; + } + } + break; + case "": + // blank string has been passed do nothing just use defaults + break; + default: // this is all for backwards compat, all a bit ugly hopfully can be removed in future + // could be either set alpha or just an int + if (name == "setalpha") + { + alpha = 0; // set the texture to have transparent background (maintains backwards compat) + } + else + { + // this function used to accept an int on its own that represented both + // width and height, this is to maintain backwards compat, could be removed + // but would break existing scripts + temp = parseIntParam(name); + if (temp != -1) + { + if (temp > 1024) + temp = 1024; + + if (temp < 128) + temp = 128; + + width = temp; + height = temp; + } + } + break; + } + + } + + Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + + Graphics graph = Graphics.FromImage(bitmap); + + // this is really just to save people filling the + // background white in their scripts, only do when fully opaque + if (alpha == 255) + { + graph.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height); + } + + for (int w = 0; w < bitmap.Width; w++) + { + for (int h = 0; h < bitmap.Height; h++) + { + bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + } + } + + + GDIDraw(data, graph); + + byte[] imageJ2000 = new byte[0]; + + try + { + imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); + } + catch (Exception) + { + Console.WriteLine( + "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); + } + m_textureManager.ReturnData(id, imageJ2000); + } + + private int parseIntParam(string strInt) + { + int parsed; + try + { + parsed = Convert.ToInt32(strInt); + } + catch (Exception) + { + //Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used + // Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString()); + parsed = -1; + } + + return parsed; + + } + + +/* + private void CairoDraw(string data, System.Drawing.Graphics graph) + { + using (Win32Surface draw = new Win32Surface(graph.GetHdc())) + { + Context contex = new Context(draw); + + contex.Antialias = Antialias.None; //fastest method but low quality + contex.LineWidth = 7; + char[] lineDelimiter = { ';' }; + char[] partsDelimiter = { ',' }; + string[] lines = data.Split(lineDelimiter); + + foreach (string line in lines) + { + string nextLine = line.Trim(); + + if (nextLine.StartsWith("MoveTO")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, ref x, ref y); + contex.MoveTo(x, y); + } + else if (nextLine.StartsWith("LineTo")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, ref x, ref y); + contex.LineTo(x, y); + contex.Stroke(); + } + } + } + graph.ReleaseHdc(); + } +*/ + + private void GDIDraw(string data, Graphics graph) + { + Point startPoint = new Point(0, 0); + Point endPoint = new Point(0, 0); + Pen drawPen = new Pen(Color.Black, 7); + string fontName = "Arial"; + float fontSize = 14; + Font myFont = new Font(fontName, fontSize); + SolidBrush myBrush = new SolidBrush(Color.Black); + char[] lineDelimiter = {';'}; + char[] partsDelimiter = {','}; + string[] lines = data.Split(lineDelimiter); + + foreach (string line in lines) + { + string nextLine = line.Trim(); + //replace with switch, or even better, do some proper parsing + if (nextLine.StartsWith("MoveTo")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); + startPoint.X = (int) x; + startPoint.Y = (int) y; + } + else if (nextLine.StartsWith("LineTo")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.DrawLine(drawPen, startPoint, endPoint); + startPoint.X = endPoint.X; + startPoint.Y = endPoint.Y; + } + else if (nextLine.StartsWith("Text")) + { + nextLine = nextLine.Remove(0, 4); + nextLine = nextLine.Trim(); + graph.DrawString(nextLine, myFont, myBrush, startPoint); + } + else if (nextLine.StartsWith("Image")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + Image image = ImageHttpRequest(nextLine); + graph.DrawImage(image, (float) startPoint.X, (float) startPoint.Y, x, y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("Rectangle")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("FillRectangle")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("Ellipse")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("FontSize")) + { + nextLine = nextLine.Remove(0, 8); + nextLine = nextLine.Trim(); + fontSize = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); + myFont = new Font(fontName, fontSize); + } + else if (nextLine.StartsWith("FontName")) + { + nextLine = nextLine.Remove(0, 8); + fontName = nextLine.Trim(); + myFont = new Font(fontName, fontSize); + } + else if (nextLine.StartsWith("PenSize")) + { + nextLine = nextLine.Remove(0, 7); + nextLine = nextLine.Trim(); + float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); + drawPen.Width = size; + } + else if (nextLine.StartsWith("PenColour")) + { + nextLine = nextLine.Remove(0, 9); + nextLine = nextLine.Trim(); + int hex = 0; + + Color newColour; + if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) + { + newColour = Color.FromArgb(hex); + } + else + { + // this doesn't fail, it just returns black if nothing is found + newColour = Color.FromName(nextLine); + } + + myBrush.Color = newColour; + drawPen.Color = newColour; + } + } + } + + private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) + { + line = line.Remove(0, startLength); + string[] parts = line.Split(partsDelimiter); + if (parts.Length == 2) + { + string xVal = parts[0].Trim(); + string yVal = parts[1].Trim(); + x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); + y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); + } + else if (parts.Length > 2) + { + string xVal = parts[0].Trim(); + string yVal = parts[1].Trim(); + x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); + y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); + + line = ""; + for (int i = 2; i < parts.Length; i++) + { + line = line + parts[i].Trim(); + line = line + " "; + } + } + } + + private Bitmap ImageHttpRequest(string url) + { + WebRequest request = HttpWebRequest.Create(url); +//Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. +//Ckrinke Stream str = null; + HttpWebResponse response = (HttpWebResponse) (request).GetResponse(); + if (response.StatusCode == HttpStatusCode.OK) + { + Bitmap image = new Bitmap(response.GetResponseStream()); + return image; + } + + return null; + } + } +} diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs new file mode 100644 index 0000000..c363940 --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -0,0 +1,726 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using OpenMetaverse; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +// using log4net; +// using System.Reflection; + + +/***************************************************** + * + * WorldCommModule + * + * + * Holding place for world comms - basically llListen + * function implementation. + * + * lLListen(integer channel, string name, key id, string msg) + * The name, id, and msg arguments specify the filtering + * criteria. You can pass the empty string + * (or NULL_KEY for id) for these to set a completely + * open filter; this causes the listen() event handler to be + * invoked for all chat on the channel. To listen only + * for chat spoken by a specific object or avatar, + * specify the name and/or id arguments. To listen + * only for a specific command, specify the + * (case-sensitive) msg argument. If msg is not empty, + * listener will only hear strings which are exactly equal + * to msg. You can also use all the arguments to establish + * the most restrictive filtering criteria. + * + * It might be useful for each listener to maintain a message + * digest, with a list of recent messages by UUID. This can + * be used to prevent in-world repeater loops. However, the + * linden functions do not have this capability, so for now + * thats the way it works. + * Instead it blocks messages originating from the same prim. + * (not Object!) + * + * For LSL compliance, note the following: + * (Tested again 1.21.1 on May 2, 2008) + * 1. 'id' has to be parsed into a UUID. None-UUID keys are + * to be replaced by the ZeroID key. (Well, TryParse does + * that for us. + * 2. Setting up an listen event from the same script, with the + * same filter settings (including step 1), returns the same + * handle as the original filter. + * 3. (TODO) handles should be script-local. Starting from 1. + * Might be actually easier to map the global handle into + * script-local handle in the ScriptEngine. Not sure if its + * worth the effort tho. + * + * **************************************************/ + +namespace OpenSim.Region.CoreModules.Scripting.WorldComm +{ + public class WorldCommModule : IRegionModule, IWorldComm + { + // private static readonly ILog m_log = + // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private ListenerManager m_listenerManager; + private Queue m_pending; + private Queue m_pendingQ; + private Scene m_scene; + private int m_whisperdistance = 10; + private int m_saydistance = 30; + private int m_shoutdistance = 100; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + // wrap this in a try block so that defaults will work if + // the config file doesn't specify otherwise. + int maxlisteners = 1000; + int maxhandles = 64; + try + { + m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); + m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); + m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); + maxlisteners = config.Configs["Chat"].GetInt("max_listens_per_region", maxlisteners); + maxhandles = config.Configs["Chat"].GetInt("max_listens_per_script", maxhandles); + } + catch (Exception) + { + } + if (maxlisteners < 1) maxlisteners = int.MaxValue; + if (maxhandles < 1) maxhandles = int.MaxValue; + + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_listenerManager = new ListenerManager(maxlisteners, maxhandles); + m_scene.EventManager.OnChatFromClient += DeliverClientMessage; + m_scene.EventManager.OnChatBroadcast += DeliverClientMessage; + m_pendingQ = new Queue(); + m_pending = Queue.Synchronized(m_pendingQ); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "WorldCommModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region IWorldComm Members + + /// + /// Create a listen event callback with the specified filters. + /// The parameters localID,itemID are needed to uniquely identify + /// the script during 'peek' time. Parameter hostID is needed to + /// determine the position of the script. + /// + /// localID of the script engine + /// UUID of the script engine + /// UUID of the SceneObjectPart + /// channel to listen on + /// name to filter on + /// key to filter on (user given, could be totally faked) + /// msg to filter on + /// number of the scripts handle + public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) + { + return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); + } + + /// + /// Sets the listen event with handle as active (active = TRUE) or inactive (active = FALSE). + /// The handle used is returned from Listen() + /// + /// UUID of the script engine + /// handle returned by Listen() + /// temp. activate or deactivate the Listen() + public void ListenControl(UUID itemID, int handle, int active) + { + if (active == 1) + m_listenerManager.Activate(itemID, handle); + else if (active == 0) + m_listenerManager.Dectivate(itemID, handle); + } + + /// + /// Removes the listen event callback with handle + /// + /// UUID of the script engine + /// handle returned by Listen() + public void ListenRemove(UUID itemID, int handle) + { + m_listenerManager.Remove(itemID, handle); + } + + /// + /// Removes all listen event callbacks for the given itemID + /// (script engine) + /// + /// UUID of the script engine + public void DeleteListener(UUID itemID) + { + m_listenerManager.DeleteListener(itemID); + } + + + protected static Vector3 CenterOfRegion = new Vector3(128, 128, 20); + + public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg) + { + Vector3 position; + SceneObjectPart source; + ScenePresence avatar; + + if ((source = m_scene.GetSceneObjectPart(id)) != null) + position = source.AbsolutePosition; + else if ((avatar = m_scene.GetScenePresence(id)) != null) + position = avatar.AbsolutePosition; + else if (ChatTypeEnum.Region == type) + position = CenterOfRegion; + else + return; + + DeliverMessage(type, channel, name, id, msg, position); + } + + /// + /// This method scans over the objects which registered an interest in listen callbacks. + /// For everyone it finds, it checks if it fits the given filter. If it does, then + /// enqueue the message for delivery to the objects listen event handler. + /// The enqueued ListenerInfo no longer has filter values, but the actually trigged values. + /// Objects that do an llSay have their messages delivered here and for nearby avatars, + /// the OnChatFromClient event is used. + /// + /// type of delvery (whisper,say,shout or regionwide) + /// channel to sent on + /// name of sender (object or avatar) + /// key of sender (object or avatar) + /// msg to sent + public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position) + { + // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}", + // type, channel, name, id, msg); + + // Determine which listen event filters match the given set of arguments, this results + // in a limited set of listeners, each belonging a host. If the host is in range, add them + // to the pending queue. + foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) + { + // Dont process if this message is from yourself! + if (li.GetHostID().Equals(id)) + continue; + + SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); + if (sPart == null) + continue; + + double dis = Util.GetDistanceTo(sPart.AbsolutePosition, position); + switch (type) + { + case ChatTypeEnum.Whisper: + if (dis < m_whisperdistance) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); + } + } + break; + + case ChatTypeEnum.Say: + if (dis < m_saydistance) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); + } + } + break; + + case ChatTypeEnum.Shout: + if (dis < m_shoutdistance) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); + } + } + break; + + case ChatTypeEnum.Region: + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); + } + break; + } + } + } + + /// + /// Are there any listen events ready to be dispatched? + /// + /// boolean indication + public bool HasMessages() + { + return (m_pending.Count > 0); + } + + /// + /// Pop the first availlable listen event from the queue + /// + /// ListenerInfo with filter filled in + public IWorldCommListenerInfo GetNextMessage() + { + ListenerInfo li = null; + + lock (m_pending.SyncRoot) + { + li = (ListenerInfo) m_pending.Dequeue(); + } + + return li; + } + + #endregion + + /******************************************************************** + * + * Listener Stuff + * + * *****************************************************************/ + + private void DeliverClientMessage(Object sender, OSChatMessage e) + { + if (null != e.Sender) + DeliverMessage(e.Type, e.Channel, e.Sender.Name, e.Sender.AgentId, e.Message, e.Position); + else + DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero, e.Message, e.Position); + } + + public Object[] GetSerializationData(UUID itemID) + { + return m_listenerManager.GetSerializationData(itemID); + } + + public void CreateFromData(uint localID, UUID itemID, UUID hostID, + Object[] data) + { + m_listenerManager.AddFromData(localID, itemID, hostID, data); + } + } + + public class ListenerManager + { + private Dictionary> m_listeners = new Dictionary>(); + private int m_maxlisteners; + private int m_maxhandles; + private int m_curlisteners; + + public ListenerManager(int maxlisteners, int maxhandles) + { + m_maxlisteners = maxlisteners; + m_maxhandles = maxhandles; + m_curlisteners = 0; + } + + public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) + { + // do we already have a match on this particular filter event? + List coll = GetListeners(itemID, channel, name, id, msg); + + if (coll.Count > 0) + { + // special case, called with same filter settings, return same handle + // (2008-05-02, tested on 1.21.1 server, still holds) + return coll[0].GetHandle(); + } + + if (m_curlisteners < m_maxlisteners) + { + int newHandle = GetNewHandle(itemID); + + if (newHandle > 0) + { + ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); + + lock (m_listeners) + { + List listeners; + if (!m_listeners.TryGetValue(channel,out listeners)) + { + listeners = new List(); + m_listeners.Add(channel, listeners); + } + listeners.Add(li); + m_curlisteners++; + } + + return newHandle; + } + } + return -1; + } + + public void Remove(UUID itemID, int handle) + { + lock (m_listeners) + { + foreach (KeyValuePair> lis in m_listeners) + { + foreach (ListenerInfo li in lis.Value) + { + if (li.GetItemID().Equals(itemID) && li.GetHandle().Equals(handle)) + { + lis.Value.Remove(li); + if (lis.Value.Count == 0) + { + m_listeners.Remove(lis.Key); + m_curlisteners--; + } + // there should be only one, so we bail out early + return; + } + } + } + } + } + + public void DeleteListener(UUID itemID) + { + List emptyChannels = new List(); + List removedListeners = new List(); + + lock (m_listeners) + { + foreach (KeyValuePair> lis in m_listeners) + { + foreach (ListenerInfo li in lis.Value) + { + if (li.GetItemID().Equals(itemID)) + { + // store them first, else the enumerated bails on us + removedListeners.Add(li); + } + } + foreach (ListenerInfo li in removedListeners) + { + lis.Value.Remove(li); + m_curlisteners--; + } + removedListeners.Clear(); + if (lis.Value.Count == 0) + { + // again, store first, remove later + emptyChannels.Add(lis.Key); + } + } + foreach (int channel in emptyChannels) + { + m_listeners.Remove(channel); + } + } + } + + public void Activate(UUID itemID, int handle) + { + lock (m_listeners) + { + foreach (KeyValuePair> lis in m_listeners) + { + foreach (ListenerInfo li in lis.Value) + { + if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) + { + li.Activate(); + // only one, bail out + return; + } + } + } + } + } + + public void Dectivate(UUID itemID, int handle) + { + lock (m_listeners) + { + foreach (KeyValuePair> lis in m_listeners) + { + foreach (ListenerInfo li in lis.Value) + { + if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) + { + li.Deactivate(); + // only one, bail out + return; + } + } + } + } + } + + // non-locked access, since its always called in the context of the lock + private int GetNewHandle(UUID itemID) + { + List handles = new List(); + + // build a list of used keys for this specific itemID... + foreach (KeyValuePair> lis in m_listeners) + { + foreach (ListenerInfo li in lis.Value) + { + if (li.GetItemID().Equals(itemID)) + handles.Add(li.GetHandle()); + } + } + + // Note: 0 is NOT a valid handle for llListen() to return + for (int i = 1; i <= m_maxhandles; i++) + { + if (!handles.Contains(i)) + return i; + } + + return -1; + } + + // Theres probably a more clever and efficient way to + // do this, maybe with regex. + // PM2008: Ha, one could even be smart and define a specialized Enumerator. + public List GetListeners(UUID itemID, int channel, string name, UUID id, string msg) + { + List collection = new List(); + + lock (m_listeners) + { + List listeners; + if (!m_listeners.TryGetValue(channel,out listeners)) + { + return collection; + } + + foreach (ListenerInfo li in listeners) + { + if (!li.IsActive()) + { + continue; + } + if (!itemID.Equals(UUID.Zero) && !li.GetItemID().Equals(itemID)) + { + continue; + } + if (li.GetName().Length > 0 && !li.GetName().Equals(name)) + { + continue; + } + if (!li.GetID().Equals(UUID.Zero) && !li.GetID().Equals(id)) + { + continue; + } + if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) + { + continue; + } + collection.Add(li); + } + } + return collection; + } + + public Object[] GetSerializationData(UUID itemID) + { + List data = new List(); + + foreach (List list in m_listeners.Values) + { + foreach (ListenerInfo l in list) + { + if (l.GetItemID() == itemID) + data.AddRange(l.GetSerializationData()); + } + } + return (Object[])data.ToArray(); + } + + public void AddFromData(uint localID, UUID itemID, UUID hostID, + Object[] data) + { + int idx = 0; + Object[] item = new Object[6]; + + while (idx < data.Length) + { + Array.Copy(data, idx, item, 0, 6); + + ListenerInfo info = + ListenerInfo.FromData(localID, itemID, hostID, item); + + if (!m_listeners.ContainsKey((int)item[2])) + m_listeners.Add((int)item[2], new List()); + m_listeners[(int)item[2]].Add(info); + + idx+=6; + } + } + } + + public class ListenerInfo: IWorldCommListenerInfo + { + private bool m_active; // Listener is active or not + private int m_handle; // Assigned handle of this listener + private uint m_localID; // Local ID from script engine + private UUID m_itemID; // ID of the host script engine + private UUID m_hostID; // ID of the host/scene part + private int m_channel; // Channel + private UUID m_id; // ID to filter messages from + private string m_name; // Object name to filter messages from + private string m_message; // The message + + public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) + { + Initialise(handle, localID, ItemID, hostID, channel, name, id, message); + } + + public ListenerInfo(ListenerInfo li, string name, UUID id, string message) + { + Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); + } + + private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, + UUID id, string message) + { + m_active = true; + m_handle = handle; + m_localID = localID; + m_itemID = ItemID; + m_hostID = hostID; + m_channel = channel; + m_name = name; + m_id = id; + m_message = message; + } + + public Object[] GetSerializationData() + { + Object[] data = new Object[6]; + + data[0] = m_active; + data[1] = m_handle; + data[2] = m_channel; + data[3] = m_name; + data[4] = m_id; + data[5] = m_message; + + return data; + } + + public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) + { + ListenerInfo linfo = new ListenerInfo((int)data[1], localID, + ItemID, hostID, (int)data[2], (string)data[3], + (UUID)data[4], (string)data[5]); + linfo.m_active=(bool)data[0]; + + return linfo; + } + + public UUID GetItemID() + { + return m_itemID; + } + + public UUID GetHostID() + { + return m_hostID; + } + + public int GetChannel() + { + return m_channel; + } + + public uint GetLocalID() + { + return m_localID; + } + + public int GetHandle() + { + return m_handle; + } + + public string GetMessage() + { + return m_message; + } + + public string GetName() + { + return m_name; + } + + public bool IsActive() + { + return m_active; + } + + public void Deactivate() + { + m_active = false; + } + + public void Activate() + { + m_active = true; + } + + public UUID GetID() + { + return m_id; + } + } +} diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs new file mode 100644 index 0000000..942c130 --- /dev/null +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -0,0 +1,726 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +/***************************************************** + * + * XMLRPCModule + * + * Module for accepting incoming communications from + * external XMLRPC client and calling a remote data + * procedure for a registered data channel/prim. + * + * + * 1. On module load, open a listener port + * 2. Attach an XMLRPC handler + * 3. When a request is received: + * 3.1 Parse into components: channel key, int, string + * 3.2 Look up registered channel listeners + * 3.3 Call the channel (prim) remote data method + * 3.4 Capture the response (llRemoteDataReply) + * 3.5 Return response to client caller + * 3.6 If no response from llRemoteDataReply within + * RemoteReplyScriptTimeout, generate script timeout fault + * + * Prims in script must: + * 1. Open a remote data channel + * 1.1 Generate a channel ID + * 1.2 Register primid,channelid pair with module + * 2. Implement the remote data procedure handler + * + * llOpenRemoteDataChannel + * llRemoteDataReply + * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval) + * llCloseRemoteDataChannel + * + * **************************************************/ + +namespace OpenSim.Region.CoreModules.Scripting.XMLRPC +{ + public class XMLRPCModule : IRegionModule, IXMLRPC + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_name = "XMLRPCModule"; + + // + private Dictionary m_openChannels; + private Dictionary m_pendingSRDResponses; + private int m_remoteDataPort = 0; + + private Dictionary m_rpcPending; + private Dictionary m_rpcPendingResponses; + private List m_scenes = new List(); + private int RemoteReplyScriptTimeout = 9000; + private int RemoteReplyScriptWait = 300; + private object XMLRPCListLock = new object(); + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + // We need to create these early because the scripts might be calling + // But since this gets called for every region, we need to make sure they + // get called only one time (or we lose any open channels) + if (null == m_openChannels) + { + m_openChannels = new Dictionary(); + m_rpcPending = new Dictionary(); + m_rpcPendingResponses = new Dictionary(); + m_pendingSRDResponses = new Dictionary(); + + try + { + m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort); + } + catch (Exception) + { + } + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + + scene.RegisterModuleInterface(this); + } + } + + public void PostInitialise() + { + if (IsEnabled()) + { + // Start http server + // Attach xmlrpc handlers + m_log.Info("[REMOTE_DATA]: " + + "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); + BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); + httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); + httpServer.Start(); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region IXMLRPC Members + + public bool IsEnabled() + { + return (m_remoteDataPort > 0); + } + + /********************************************** + * OpenXMLRPCChannel + * + * Generate a UUID channel key and add it and + * the prim id to dictionary + * + * A custom channel key can be proposed. + * Otherwise, passing UUID.Zero will generate + * and return a random channel + * + * First check if there is a channel assigned for + * this itemID. If there is, then someone called + * llOpenRemoteDataChannel twice. Just return the + * original channel. Other option is to delete the + * current channel and assign a new one. + * + * ********************************************/ + + public UUID OpenXMLRPCChannel(uint localID, UUID itemID, UUID channelID) + { + UUID newChannel = UUID.Zero; + + // This should no longer happen, but the check is reasonable anyway + if (null == m_openChannels) + { + m_log.Warn("[RemoteDataReply] Attempt to open channel before initialization is complete"); + return newChannel; + } + + //Is a dupe? + foreach (RPCChannelInfo ci in m_openChannels.Values) + { + if (ci.GetItemID().Equals(itemID)) + { + // return the original channel ID for this item + newChannel = ci.GetChannelID(); + break; + } + } + + if (newChannel == UUID.Zero) + { + newChannel = (channelID == UUID.Zero) ? UUID.Random() : channelID; + RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, newChannel); + lock (XMLRPCListLock) + { + m_openChannels.Add(newChannel, rpcChanInfo); + } + } + + return newChannel; + } + + // Delete channels based on itemID + // for when a script is deleted + public void DeleteChannels(UUID itemID) + { + if (m_openChannels != null) + { + ArrayList tmp = new ArrayList(); + + lock (XMLRPCListLock) + { + foreach (RPCChannelInfo li in m_openChannels.Values) + { + if (li.GetItemID().Equals(itemID)) + { + tmp.Add(itemID); + } + } + + IEnumerator tmpEnumerator = tmp.GetEnumerator(); + while (tmpEnumerator.MoveNext()) + m_openChannels.Remove((UUID) tmpEnumerator.Current); + } + } + } + + /********************************************** + * Remote Data Reply + * + * Response to RPC message + * + *********************************************/ + + public void RemoteDataReply(string channel, string message_id, string sdata, int idata) + { + UUID message_key = new UUID(message_id); + UUID channel_key = new UUID(channel); + + RPCRequestInfo rpcInfo = null; + + if (message_key == UUID.Zero) + { + foreach (RPCRequestInfo oneRpcInfo in m_rpcPendingResponses.Values) + if (oneRpcInfo.GetChannelKey() == channel_key) + rpcInfo = oneRpcInfo; + } + else + { + m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo); + } + + if (rpcInfo != null) + { + rpcInfo.SetStrRetval(sdata); + rpcInfo.SetIntRetval(idata); + rpcInfo.SetProcessed(true); + m_rpcPendingResponses.Remove(message_key); + } + else + { + m_log.Warn("[RemoteDataReply]: Channel or message_id not found"); + } + } + + /********************************************** + * CloseXMLRPCChannel + * + * Remove channel from dictionary + * + *********************************************/ + + public void CloseXMLRPCChannel(UUID channelKey) + { + if (m_openChannels.ContainsKey(channelKey)) + m_openChannels.Remove(channelKey); + } + + + public bool hasRequests() + { + lock (XMLRPCListLock) + { + if (m_rpcPending != null) + return (m_rpcPending.Count > 0); + else + return false; + } + } + + public IXmlRpcRequestInfo GetNextCompletedRequest() + { + if (m_rpcPending != null) + { + lock (XMLRPCListLock) + { + foreach (UUID luid in m_rpcPending.Keys) + { + RPCRequestInfo tmpReq; + + if (m_rpcPending.TryGetValue(luid, out tmpReq)) + { + if (!tmpReq.IsProcessed()) return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedRequest(UUID id) + { + lock (XMLRPCListLock) + { + RPCRequestInfo tmp; + if (m_rpcPending.TryGetValue(id, out tmp)) + { + m_rpcPending.Remove(id); + m_rpcPendingResponses.Add(id, tmp); + } + else + { + Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST"); + } + } + } + + public UUID SendRemoteData(uint localID, UUID itemID, string channel, string dest, int idata, string sdata) + { + SendRemoteDataRequest req = new SendRemoteDataRequest( + localID, itemID, channel, dest, idata, sdata + ); + m_pendingSRDResponses.Add(req.GetReqID(), req); + req.Process(); + return req.ReqID; + } + + public IServiceRequest GetNextCompletedSRDRequest() + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (UUID luid in m_pendingSRDResponses.Keys) + { + SendRemoteDataRequest tmpReq; + + if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.Finished) + return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedSRDRequest(UUID id) + { + lock (XMLRPCListLock) + { + SendRemoteDataRequest tmpReq; + if (m_pendingSRDResponses.TryGetValue(id, out tmpReq)) + { + m_pendingSRDResponses.Remove(id); + } + } + } + + public void CancelSRDRequests(UUID itemID) + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values) + { + if (li.ItemID.Equals(itemID)) + m_pendingSRDResponses.Remove(li.GetReqID()); + } + } + } + } + + #endregion + + public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + + Hashtable requestData = (Hashtable) request.Params[0]; + bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && + requestData.Contains("StringValue")); + + if (GoodXML) + { + UUID channel = new UUID((string) requestData["Channel"]); + RPCChannelInfo rpcChanInfo; + if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) + { + string intVal = Convert.ToInt32(requestData["IntValue"]).ToString(); + string strVal = (string) requestData["StringValue"]; + + RPCRequestInfo rpcInfo; + + lock (XMLRPCListLock) + { + rpcInfo = + new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, + intVal); + m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo); + } + + int timeoutCtr = 0; + + while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout)) + { + Thread.Sleep(RemoteReplyScriptWait); + timeoutCtr += RemoteReplyScriptWait; + } + if (rpcInfo.IsProcessed()) + { + Hashtable param = new Hashtable(); + param["StringValue"] = rpcInfo.GetStrRetval(); + param["IntValue"] = rpcInfo.GetIntRetval(); + + ArrayList parameters = new ArrayList(); + parameters.Add(param); + + response.Value = parameters; + rpcInfo = null; + } + else + { + response.SetFault(-1, "Script timeout"); + rpcInfo = null; + } + } + else + { + response.SetFault(-1, "Invalid channel"); + } + } + + return response; + } + } + + public class RPCRequestInfo: IXmlRpcRequestInfo + { + private UUID m_ChannelKey; + private string m_IntVal; + private UUID m_ItemID; + private uint m_localID; + private UUID m_MessageID; + private bool m_processed; + private int m_respInt; + private string m_respStr; + private string m_StrVal; + + public RPCRequestInfo(uint localID, UUID itemID, UUID channelKey, string strVal, string intVal) + { + m_localID = localID; + m_StrVal = strVal; + m_IntVal = intVal; + m_ItemID = itemID; + m_ChannelKey = channelKey; + m_MessageID = UUID.Random(); + m_processed = false; + m_respStr = String.Empty; + m_respInt = 0; + } + + public bool IsProcessed() + { + return m_processed; + } + + public UUID GetChannelKey() + { + return m_ChannelKey; + } + + public void SetProcessed(bool processed) + { + m_processed = processed; + } + + public void SetStrRetval(string resp) + { + m_respStr = resp; + } + + public string GetStrRetval() + { + return m_respStr; + } + + public void SetIntRetval(int resp) + { + m_respInt = resp; + } + + public int GetIntRetval() + { + return m_respInt; + } + + public uint GetLocalID() + { + return m_localID; + } + + public UUID GetItemID() + { + return m_ItemID; + } + + public string GetStrVal() + { + return m_StrVal; + } + + public int GetIntValue() + { + return int.Parse(m_IntVal); + } + + public UUID GetMessageID() + { + return m_MessageID; + } + } + + public class RPCChannelInfo + { + private UUID m_ChannelKey; + private UUID m_itemID; + private uint m_localID; + + public RPCChannelInfo(uint localID, UUID itemID, UUID channelID) + { + m_ChannelKey = channelID; + m_localID = localID; + m_itemID = itemID; + } + + public UUID GetItemID() + { + return m_itemID; + } + + public UUID GetChannelID() + { + return m_ChannelKey; + } + + public uint GetLocalID() + { + return m_localID; + } + } + + public class SendRemoteDataRequest: IServiceRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public string Channel; + public string DestURL; + private bool _finished; + public bool Finished + { + get { return _finished; } + set { _finished = value; } + } + private Thread httpThread; + public int Idata; + private UUID _itemID; + public UUID ItemID + { + get { return _itemID; } + set { _itemID = value; } + } + private uint _localID; + public uint LocalID + { + get { return _localID; } + set { _localID = value; } + } + private UUID _reqID; + public UUID ReqID + { + get { return _reqID; } + set { _reqID = value; } + } + public XmlRpcRequest Request; + public int ResponseIdata; + public string ResponseSdata; + public string Sdata; + + public SendRemoteDataRequest(uint localID, UUID itemID, string channel, string dest, int idata, string sdata) + { + this.Channel = channel; + DestURL = dest; + this.Idata = idata; + this.Sdata = sdata; + ItemID = itemID; + LocalID = localID; + + ReqID = UUID.Random(); + } + + public void Process() + { + httpThread = new Thread(SendRequest); + httpThread.Name = "HttpRequestThread"; + httpThread.Priority = ThreadPriority.BelowNormal; + httpThread.IsBackground = true; + _finished = false; + httpThread.Start(); + ThreadTracker.Add(httpThread); + } + + /* + * TODO: More work on the response codes. Right now + * returning 200 for success or 499 for exception + */ + + public void SendRequest() + { + Hashtable param = new Hashtable(); + + // Check if channel is an UUID + // if not, use as method name + UUID parseUID; + string mName = "llRemoteData"; + if ((Channel != null) && (Channel != "")) + if (!UUID.TryParse(Channel, out parseUID)) + mName = Channel; + else + param["Channel"] = Channel; + + param["StringValue"] = Sdata; + param["IntValue"] = Convert.ToString(Idata); + + ArrayList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest(mName, parameters); + try + { + XmlRpcResponse resp = req.Send(DestURL, 30000); + if (resp != null) + { + Hashtable respParms; + if (resp.Value.GetType().Equals(typeof(System.Collections.Hashtable))) + { + respParms = (Hashtable) resp.Value; + } + else + { + ArrayList respData = (ArrayList) resp.Value; + respParms = (Hashtable) respData[0]; + } + if (respParms != null) + { + if (respParms.Contains("StringValue")) + { + Sdata = (string) respParms["StringValue"]; + } + if (respParms.Contains("IntValue")) + { + Idata = Convert.ToInt32((string) respParms["IntValue"]); + } + if (respParms.Contains("faultString")) + { + Sdata = (string) respParms["faultString"]; + } + if (respParms.Contains("faultCode")) + { + Idata = Convert.ToInt32(respParms["faultCode"]); + } + } + } + } + catch (Exception we) + { + Sdata = we.Message; + m_log.Warn("[SendRemoteDataRequest]: Request failed"); + m_log.Warn(we.StackTrace); + } + + _finished = true; + } + + public void Stop() + { + try + { + httpThread.Abort(); + } + catch (Exception) + { + } + } + + public UUID GetReqID() + { + return ReqID; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveConstants.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveConstants.cs new file mode 100644 index 0000000..179d1a2 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveConstants.cs @@ -0,0 +1,128 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections.Generic; +using OpenMetaverse; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Constants for the archiving module + /// + public class ArchiveConstants + { + /// + /// The location of the archive control file + /// + public static readonly string CONTROL_FILE_PATH = "archive.xml"; + + /// + /// Path for the assets held in an archive + /// + public static readonly string ASSETS_PATH = "assets/"; + + /// + /// Path for the assets metadata file + /// + //public static readonly string ASSETS_METADATA_PATH = "assets.xml"; + + /// + /// Path for the prims file + /// + public static readonly string OBJECTS_PATH = "objects/"; + + /// + /// Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. + /// + public static readonly string TERRAINS_PATH = "terrains/"; + + /// + /// Path for region settings. + /// + public static readonly string SETTINGS_PATH = "settings/"; + + /// + /// The character the separates the uuid from extension information in an archived asset filename + /// + public static readonly string ASSET_EXTENSION_SEPARATOR = "_"; + + /// + /// Extensions used for asset types in the archive + /// + public static readonly IDictionary ASSET_TYPE_TO_EXTENSION = new Dictionary(); + public static readonly IDictionary EXTENSION_TO_ASSET_TYPE = new Dictionary(); + + static ArchiveConstants() + { + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Animation] = ASSET_EXTENSION_SEPARATOR + "animation.bvh"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Bodypart] = ASSET_EXTENSION_SEPARATOR + "bodypart.txt"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.CallingCard] = ASSET_EXTENSION_SEPARATOR + "callingcard.txt"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Clothing] = ASSET_EXTENSION_SEPARATOR + "clothing.txt"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Folder] = ASSET_EXTENSION_SEPARATOR + "folder.txt"; // Not sure if we'll ever see this + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Gesture] = ASSET_EXTENSION_SEPARATOR + "gesture.txt"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageJPEG] = ASSET_EXTENSION_SEPARATOR + "image.jpg"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageTGA] = ASSET_EXTENSION_SEPARATOR + "image.tga"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Landmark] = ASSET_EXTENSION_SEPARATOR + "landmark.txt"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LostAndFoundFolder] = ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"; // Not sure if we'll ever see this + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLBytecode] = ASSET_EXTENSION_SEPARATOR + "bytecode.lso"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLText] = ASSET_EXTENSION_SEPARATOR + "script.lsl"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Notecard] = ASSET_EXTENSION_SEPARATOR + "notecard.txt"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Object] = ASSET_EXTENSION_SEPARATOR + "object.xml"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.RootFolder] = ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"; // Not sure if we'll ever see this + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Simstate] = ASSET_EXTENSION_SEPARATOR + "simstate.bin"; // Not sure if we'll ever see this + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SnapshotFolder] = ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"; // Not sure if we'll ever see this + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Sound] = ASSET_EXTENSION_SEPARATOR + "sound.ogg"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV] = ASSET_EXTENSION_SEPARATOR + "sound.wav"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this + + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "callingcard.txt"] = (sbyte)AssetType.CallingCard; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "clothing.txt"] = (sbyte)AssetType.Clothing; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "folder.txt"] = (sbyte)AssetType.Folder; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "gesture.txt"] = (sbyte)AssetType.Gesture; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.jpg"] = (sbyte)AssetType.ImageJPEG; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.tga"] = (sbyte)AssetType.ImageTGA; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "landmark.txt"] = (sbyte)AssetType.Landmark; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"] = (sbyte)AssetType.LostAndFoundFolder; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bytecode.lso"] = (sbyte)AssetType.LSLBytecode; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "script.lsl"] = (sbyte)AssetType.LSLText; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "notecard.txt"] = (sbyte)AssetType.Notecard; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "object.xml"] = (sbyte)AssetType.Object; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"] = (sbyte)AssetType.RootFolder; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "simstate.bin"] = (sbyte)AssetType.Simstate; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"] = (sbyte)AssetType.SnapshotFolder; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.ogg"] = (sbyte)AssetType.Sound; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.wav"] = (sbyte)AssetType.SoundWAV; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs new file mode 100644 index 0000000..3218abc --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -0,0 +1,460 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using System.Xml; +using System.Net; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Terrain; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Handles an individual archive read request + /// + public class ArchiveReadRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); + + private Scene m_scene; + private Stream m_loadStream; + private string m_errorMessage; + + /// + /// Used to cache lookups for valid uuids. + /// + private IDictionary m_validUserUuids = new Dictionary(); + + public ArchiveReadRequest(Scene scene, string loadPath) + { + m_scene = scene; + m_loadStream = new GZipStream(GetStream(loadPath), CompressionMode.Decompress); + m_errorMessage = String.Empty; + } + + public ArchiveReadRequest(Scene scene, Stream loadStream) + { + m_scene = scene; + m_loadStream = loadStream; + } + + /// + /// Dearchive the region embodied in this request. + /// + public void DearchiveRegion() + { + // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions + DearchiveRegion0DotStar(); + } + + private void DearchiveRegion0DotStar() + { + int successfulAssetRestores = 0; + int failedAssetRestores = 0; + List serialisedSceneObjects = new List(); + + try + { + TarArchiveReader archive = new TarArchiveReader(m_loadStream); + + //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache); + + string filePath = "ERROR"; + + byte[] data; + TarArchiveReader.TarEntryType entryType; + + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + { + //m_log.DebugFormat( + // "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length); + if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) + { + m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", + filePath); + } + else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) + { + serialisedSceneObjects.Add(m_asciiEncoding.GetString(data)); + } +// else if (filePath.Equals(ArchiveConstants.ASSETS_METADATA_PATH)) +// { +// string xml = m_asciiEncoding.GetString(data); +// dearchiver.AddAssetMetadata(xml); +// } + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + if (LoadAsset(filePath, data)) + successfulAssetRestores++; + else + failedAssetRestores++; + } + else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) + { + LoadTerrain(filePath, data); + } + else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) + { + LoadRegionSettings(filePath, data); + } + } + + //m_log.Debug("[ARCHIVER]: Reached end of archive"); + + archive.Close(); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ARCHIVER]: Error loading oar file. Exception was: {0}", e); + m_errorMessage += e.ToString(); + m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage); + return; + } + + m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); + + if (failedAssetRestores > 0) + { + m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); + m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); + } + + m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); + m_scene.DeleteAllSceneObjects(); + + // Reload serialized prims + m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); + + IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface(); + ICollection sceneObjects = new List(); + + foreach (string serialisedSceneObject in serialisedSceneObjects) + { + SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); + + // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned + // on the same region server and multiple examples a single object archive to be imported + // to the same scene (when this is possible). + sceneObject.ResetIDs(); + + // Try to retain the original creator/owner/lastowner if their uuid is present on this grid + // otherwise, use the master avatar uuid instead + UUID masterAvatarId = m_scene.RegionInfo.MasterAvatarAssignedUUID; + + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + masterAvatarId = m_scene.RegionInfo.EstateSettings.EstateOwner; + + foreach (SceneObjectPart part in sceneObject.Children.Values) + { + if (!resolveUserUuid(part.CreatorID)) + part.CreatorID = masterAvatarId; + + if (!resolveUserUuid(part.OwnerID)) + part.OwnerID = masterAvatarId; + + if (!resolveUserUuid(part.LastOwnerID)) + part.LastOwnerID = masterAvatarId; + + // And zap any troublesome sit target information + part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); + part.SitTargetPosition = new Vector3(0, 0, 0); + + // Fix ownership/creator of inventory items + // Not doing so results in inventory items + // being no copy/no mod for everyone + TaskInventoryDictionary inv = part.TaskInventory; + foreach (KeyValuePair kvp in inv) + { + if (!resolveUserUuid(kvp.Value.OwnerID)) + { + kvp.Value.OwnerID = masterAvatarId; + } + if (!resolveUserUuid(kvp.Value.CreatorID)) + { + kvp.Value.CreatorID = masterAvatarId; + } + } + } + + if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) + { + sceneObjects.Add(sceneObject); + } + } + + m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjects.Count); + + int ignoredObjects = serialisedSceneObjects.Count - sceneObjects.Count; + + if (ignoredObjects > 0) + m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); + + m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); + + m_log.Debug("[ARCHIVER]: Starting scripts"); + + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + sceneObject.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 0); + } + + m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage); + } + + /// + /// Look up the given user id to check whether it's one that is valid for this grid. + /// + /// + /// + private bool resolveUserUuid(UUID uuid) + { + if (!m_validUserUuids.ContainsKey(uuid)) + { + CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(uuid); + if (profile != null && profile.UserProfile != null) + m_validUserUuids.Add(uuid, true); + else + m_validUserUuids.Add(uuid, false); + } + + if (m_validUserUuids[uuid]) + return true; + else + return false; + } + + /// + /// Load an asset + /// + /// + /// + /// true if asset was successfully loaded, false otherwise + private bool LoadAsset(string assetPath, byte[] data) + { + // Right now we're nastily obtaining the UUID from the filename + string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); + int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR); + + if (i == -1) + { + m_log.ErrorFormat( + "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping", + assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR); + + return false; + } + + string extension = filename.Substring(i); + string uuid = filename.Remove(filename.Length - extension.Length); + + if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) + { + sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; + + //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); + + AssetBase asset = new AssetBase(new UUID(uuid), String.Empty); + asset.Metadata.Type = assetType; + asset.Data = data; + + m_scene.AssetCache.AddAsset(asset); + + /** + * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so + * it might be best done when dearchive takes place on a separate thread + if (asset.Type=AssetType.Texture) + { + IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface(); + if (cacheLayerDecode != null) + cacheLayerDecode.syncdecode(asset.FullID, asset.Data); + } + */ + + return true; + } + else + { + m_log.ErrorFormat( + "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}", + assetPath, extension); + + return false; + } + } + + /// + /// Load region settings data + /// + /// + /// + /// + /// true if settings were loaded successfully, false otherwise + /// + private bool LoadRegionSettings(string settingsPath, byte[] data) + { + RegionSettings loadedRegionSettings; + + try + { + loadedRegionSettings = RegionSettingsSerializer.Deserialize(data); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}", + settingsPath, e); + return false; + } + + RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; + + currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; + currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; + currentRegionSettings.AllowLandJoinDivide = loadedRegionSettings.AllowLandJoinDivide; + currentRegionSettings.AllowLandResell = loadedRegionSettings.AllowLandResell; + currentRegionSettings.BlockFly = loadedRegionSettings.BlockFly; + currentRegionSettings.BlockShowInSearch = loadedRegionSettings.BlockShowInSearch; + currentRegionSettings.BlockTerraform = loadedRegionSettings.BlockTerraform; + currentRegionSettings.DisableCollisions = loadedRegionSettings.DisableCollisions; + currentRegionSettings.DisablePhysics = loadedRegionSettings.DisablePhysics; + currentRegionSettings.DisableScripts = loadedRegionSettings.DisableScripts; + currentRegionSettings.Elevation1NE = loadedRegionSettings.Elevation1NE; + currentRegionSettings.Elevation1NW = loadedRegionSettings.Elevation1NW; + currentRegionSettings.Elevation1SE = loadedRegionSettings.Elevation1SE; + currentRegionSettings.Elevation1SW = loadedRegionSettings.Elevation1SW; + currentRegionSettings.Elevation2NE = loadedRegionSettings.Elevation2NE; + currentRegionSettings.Elevation2NW = loadedRegionSettings.Elevation2NW; + currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE; + currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW; + currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun; + currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus; + currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing; + currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit; + currentRegionSettings.TerrainRaiseLimit = loadedRegionSettings.TerrainRaiseLimit; + currentRegionSettings.TerrainTexture1 = loadedRegionSettings.TerrainTexture1; + currentRegionSettings.TerrainTexture2 = loadedRegionSettings.TerrainTexture2; + currentRegionSettings.TerrainTexture3 = loadedRegionSettings.TerrainTexture3; + currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4; + currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun; + currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; + + IEstateModule estateModule = m_scene.RequestModuleInterface(); + estateModule.sendRegionHandshakeToAll(); + + return true; + } + + /// + /// Load terrain data + /// + /// + /// + /// + /// true if terrain was resolved successfully, false otherwise. + /// + private bool LoadTerrain(string terrainPath, byte[] data) + { + ITerrainModule terrainModule = m_scene.RequestModuleInterface(); + + MemoryStream ms = new MemoryStream(data); + terrainModule.LoadFromStream(terrainPath, ms); + ms.Close(); + + m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath); + + return true; + } + + /// + /// Resolve path to a working FileStream + /// + private Stream GetStream(string path) + { + try + { + if (File.Exists(path)) + { + return new FileStream(path, FileMode.Open); + } + else + { + Uri uri = new Uri(path); // throw exception if not valid URI + if (uri.Scheme == "file") + { + return new FileStream(uri.AbsolutePath, FileMode.Open); + } + else + { + if (uri.Scheme != "http") + throw new Exception(String.Format("Unsupported URI scheme ({0})", path)); + + // OK, now we know we have an HTTP URI to work with + + return URIFetch(uri); + } + } + } + catch (Exception e) + { + throw new Exception(String.Format("Unable to create file input stream for {0}: {1}", path, e)); + } + } + + private static Stream URIFetch(Uri uri) + { + HttpWebRequest request = (HttpWebRequest) WebRequest.Create(uri); + + // request.Credentials = credentials; + + request.ContentLength = 0; + + WebResponse response = request.GetResponse(); + Stream file = response.GetResponseStream(); + + if (response.ContentType != "application/x-oar") + throw new Exception(String.Format("{0} does not identify an OAR file", uri.ToString())); + + if (response.ContentLength == 0) + throw new Exception(String.Format("{0} returned an empty file", uri.ToString())); + + // return new BufferedStream(file, (int) response.ContentLength); + return new BufferedStream(file, 1000000); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs new file mode 100644 index 0000000..d3c2cd1 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs @@ -0,0 +1,161 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.World.Terrain; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Method called when all the necessary assets for an archive request have been received. + /// + public delegate void AssetsRequestCallback(IDictionary assetsFound, ICollection assetsNotFoundUuids); + + /// + /// Execute the write of an archive once we have received all the necessary data + /// + public class ArchiveWriteRequestExecution + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected ITerrainModule m_terrainModule; + protected IRegionSerialiserModule m_serialiser; + protected List m_sceneObjects; + protected Scene m_scene; + protected Stream m_saveStream; + + public ArchiveWriteRequestExecution( + List sceneObjects, + ITerrainModule terrainModule, + IRegionSerialiserModule serialiser, + Scene scene, + Stream saveStream) + { + m_sceneObjects = sceneObjects; + m_terrainModule = terrainModule; + m_serialiser = serialiser; + m_scene = scene; + m_saveStream = saveStream; + } + + protected internal void ReceivedAllAssets( + IDictionary assetsFound, ICollection assetsNotFoundUuids) + { + foreach (UUID uuid in assetsNotFoundUuids) + { + m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); + } + + m_log.InfoFormat( + "[ARCHIVER]: Received {0} of {1} assets requested", + assetsFound.Count, assetsFound.Count + assetsNotFoundUuids.Count); + + m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); + + TarArchiveWriter archive = new TarArchiveWriter(); + + // Write out control file + archive.AddFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile()); + + // Write out region settings + string settingsPath + = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); + archive.AddFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); + + // Write out terrain + string terrainPath + = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); + + MemoryStream ms = new MemoryStream(); + m_terrainModule.SaveToStream(terrainPath, ms); + archive.AddFile(terrainPath, ms.ToArray()); + ms.Close(); + + // Write out scene object metadata + foreach (SceneObjectGroup sceneObject in m_sceneObjects) + { + //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); + + Vector3 position = sceneObject.AbsolutePosition; + + string serializedObject = m_serialiser.SaveGroupToXml2(sceneObject); + string filename + = string.Format( + "{0}{1}_{2:000}-{3:000}-{4:000}__{5}.xml", + ArchiveConstants.OBJECTS_PATH, sceneObject.Name, + Math.Round(position.X), Math.Round(position.Y), Math.Round(position.Z), + sceneObject.UUID); + + archive.AddFile(filename, serializedObject); + } + + // Write out assets + AssetsArchiver assetsArchiver = new AssetsArchiver(assetsFound); + assetsArchiver.Archive(archive); + + archive.WriteTar(m_saveStream); + + m_log.InfoFormat("[ARCHIVER]: Wrote out OpenSimulator archive for {0}", m_scene.RegionInfo.RegionName); + + m_scene.EventManager.TriggerOarFileSaved(String.Empty); + } + + /// + /// Create the control file for a 0.2 version archive + /// + /// + public static string Create0p2ControlFile() + { + StringWriter sw = new StringWriter(); + XmlTextWriter xtw = new XmlTextWriter(sw); + xtw.Formatting = Formatting.Indented; + xtw.WriteStartDocument(); + xtw.WriteStartElement("archive"); + xtw.WriteAttributeString("major_version", "0"); + xtw.WriteAttributeString("minor_version", "2"); + xtw.WriteEndElement(); + + xtw.Flush(); + xtw.Close(); + + String s = sw.ToString(); + sw.Close(); + + return s; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs new file mode 100644 index 0000000..ee0ec69 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -0,0 +1,333 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.World.Terrain; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Prepare to write out an archive. + /// + public class ArchiveWriteRequestPreparation + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + protected Stream m_saveStream; + + /// + /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate + /// asset was found by the asset service. + /// + protected AssetBase m_requestedObjectAsset; + + /// + /// Signal whether we are currently waiting for the asset service to deliver an asset. + /// + protected bool m_waitingForObjectAsset; + + /// + /// Constructor + /// + public ArchiveWriteRequestPreparation(Scene scene, string savePath) + { + m_scene = scene; + m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress); + } + + /// + /// Constructor. + /// + /// + /// The stream to which to save data. + public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream) + { + m_scene = scene; + m_saveStream = saveStream; + } + + /// + /// The callback made when we request the asset for an object from the asset service. + /// + public void AssetRequestCallback(UUID assetID, AssetBase asset) + { + lock (this) + { + m_requestedObjectAsset = asset; + m_waitingForObjectAsset = false; + Monitor.Pulse(this); + } + } + + /// + /// Get an asset synchronously, potentially using an asynchronous callback. If the + /// asynchronous callback is used, we will wait for it to complete. + /// + /// + /// + protected AssetBase GetAsset(UUID uuid) + { + m_waitingForObjectAsset = true; + m_scene.AssetCache.GetAsset(uuid, AssetRequestCallback, true); + + // The asset cache callback can either + // + // 1. Complete on the same thread (if the asset is already in the cache) or + // 2. Come in via a different thread (if we need to go fetch it). + // + // The code below handles both these alternatives. + lock (this) + { + if (m_waitingForObjectAsset) + { + Monitor.Wait(this); + m_waitingForObjectAsset = false; + } + } + + return m_requestedObjectAsset; + } + + /// + /// Record the asset uuids embedded within the given script. + /// + /// + /// Dictionary in which to record the references + protected void GetScriptAssetUuids(UUID scriptUuid, IDictionary assetUuids) + { + AssetBase scriptAsset = GetAsset(scriptUuid); + + if (null != scriptAsset) + { + string script = Utils.BytesToString(scriptAsset.Data); + //m_log.DebugFormat("[ARCHIVER]: Script {0}", script); + MatchCollection uuidMatches = Util.UUIDPattern.Matches(script); + //m_log.DebugFormat("[ARCHIVER]: Found {0} matches in script", uuidMatches.Count); + + foreach (Match uuidMatch in uuidMatches) + { + UUID uuid = new UUID(uuidMatch.Value); + //m_log.DebugFormat("[ARCHIVER]: Recording {0} in script", uuid); + assetUuids[uuid] = 1; + } + } + } + + /// + /// Record the uuids referenced by the given wearable asset + /// + /// + /// Dictionary in which to record the references + protected void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary assetUuids) + { + AssetBase assetBase = GetAsset(wearableAssetUuid); + //m_log.Debug(new System.Text.ASCIIEncoding().GetString(bodypartAsset.Data)); + AssetWearable wearableAsset = new AssetBodypart(wearableAssetUuid, assetBase.Data); + wearableAsset.Decode(); + + //m_log.DebugFormat( + // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); + + foreach (UUID uuid in wearableAsset.Textures.Values) + { + //m_log.DebugFormat("[ARCHIVER]: Got bodypart uuid {0}", uuid); + assetUuids[uuid] = 1; + } + } + + /// + /// Get all the asset uuids associated with a given object. This includes both those directly associated with + /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained + /// within this object). + /// + /// + /// + protected void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary assetUuids) + { + AssetBase objectAsset = GetAsset(sceneObjectUuid); + + if (null != objectAsset) + { + string xml = Utils.BytesToString(objectAsset.Data); + SceneObjectGroup sog = new SceneObjectGroup(xml, true); + GetSceneObjectAssetUuids(sog, assetUuids); + } + } + + /// + /// Get all the asset uuids associated with a given object. This includes both those directly associated with + /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained + /// within this object). + /// + /// + /// + protected void GetSceneObjectAssetUuids(SceneObjectGroup sceneObject, IDictionary assetUuids) + { + m_log.DebugFormat( + "[ARCHIVER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); + + foreach (SceneObjectPart part in sceneObject.GetParts()) + { + //m_log.DebugFormat( + // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); + + try + { + Primitive.TextureEntry textureEntry = part.Shape.Textures; + + // Get the prim's default texture. This will be used for faces which don't have their own texture + assetUuids[textureEntry.DefaultTexture.TextureID] = 1; + + // XXX: Not a great way to iterate through face textures, but there's no + // other method available to tell how many faces there actually are + //int i = 0; + foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) + { + if (texture != null) + { + //m_log.DebugFormat("[ARCHIVER]: Got face {0}", i++); + assetUuids[texture.TextureID] = 1; + } + } + + // If the prim is a sculpt then preserve this information too + if (part.Shape.SculptTexture != UUID.Zero) + assetUuids[part.Shape.SculptTexture] = 1; + + // Now analyze this prim's inventory items to preserve all the uuids that they reference + foreach (TaskInventoryItem tii in part.TaskInventory.Values) + { + //m_log.DebugFormat("[ARCHIVER]: Analysing item asset type {0}", tii.Type); + + if (!assetUuids.ContainsKey(tii.AssetID)) + { + assetUuids[tii.AssetID] = 1; + + if ((int)AssetType.Bodypart == tii.Type || ((int)AssetType.Clothing == tii.Type)) + { + GetWearableAssetUuids(tii.AssetID, assetUuids); + } + else if ((int)AssetType.LSLText == tii.Type) + { + GetScriptAssetUuids(tii.AssetID, assetUuids); + } + else if ((int)AssetType.Object == tii.Type) + { + GetSceneObjectAssetUuids(tii.AssetID, assetUuids); + } + //else + //{ + //m_log.DebugFormat("[ARCHIVER]: Recording asset {0} in object {1}", tii.AssetID, part.UUID); + //} + } + } + } + catch (Exception e) + { + m_log.ErrorFormat("[ARCHIVER]: Failed to get part - {0}", e); + m_log.DebugFormat("[ARCHIVER]: Texture entry length for prim was {0} (min is 46)", part.Shape.TextureEntry.Length); + } + } + } + + /// + /// Archive the region requested. + /// + /// if there was an io problem with creating the file + public void ArchiveRegion() + { + Dictionary assetUuids = new Dictionary(); + + List entities = m_scene.GetEntities(); + List sceneObjects = new List(); + + // Filter entities so that we only have scene objects. + // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods + // end up having to do this + foreach (EntityBase entity in entities) + { + if (entity is SceneObjectGroup) + { + SceneObjectGroup sceneObject = (SceneObjectGroup)entity; + + if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) + sceneObjects.Add((SceneObjectGroup)entity); + } + } + + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + GetSceneObjectAssetUuids(sceneObject, assetUuids); + } + + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", + sceneObjects.Count, assetUuids.Count); + + // Make sure that we also request terrain texture assets + RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; + + if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) + assetUuids[regionSettings.TerrainTexture1] = 1; + + if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) + assetUuids[regionSettings.TerrainTexture2] = 1; + + if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) + assetUuids[regionSettings.TerrainTexture3] = 1; + + if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) + assetUuids[regionSettings.TerrainTexture4] = 1; + + // Asynchronously request all the assets required to perform this archive operation + ArchiveWriteRequestExecution awre + = new ArchiveWriteRequestExecution( + sceneObjects, + m_scene.RequestModuleInterface(), + m_scene.RequestModuleInterface(), + m_scene, + m_saveStream); + + new AssetsRequest(assetUuids.Keys, m_scene.AssetCache, awre.ReceivedAllAssets).Execute(); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs new file mode 100644 index 0000000..c1f5b18 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -0,0 +1,95 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Serialiser; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// This module loads and saves OpenSimulator archives + /// + public class ArchiverModule : IRegionModule, IRegionArchiverModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + + public string Name { get { return "Archiver Module"; } } + + public bool IsSharedModule { get { return false; } } + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public void ArchiveRegion(string savePath) + { + m_log.InfoFormat( + "[ARCHIVER]: Writing archive for region {0} to {1}", m_scene.RegionInfo.RegionName, savePath); + + new ArchiveWriteRequestPreparation(m_scene, savePath).ArchiveRegion(); + } + + public void ArchiveRegion(Stream saveStream) + { + new ArchiveWriteRequestPreparation(m_scene, saveStream).ArchiveRegion(); + } + + public void DearchiveRegion(string loadPath) + { + m_log.InfoFormat( + "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath); + + new ArchiveReadRequest(m_scene, loadPath).DearchiveRegion(); + } + + public void DearchiveRegion(Stream loadStream) + { + new ArchiveReadRequest(m_scene, loadStream).DearchiveRegion(); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs new file mode 100644 index 0000000..76d27ce --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs @@ -0,0 +1,143 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Archives assets + /// + public class AssetsArchiver + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Archive assets + /// + protected IDictionary m_assets; + + public AssetsArchiver(IDictionary assets) + { + m_assets = assets; + } + + /// + /// Archive the assets given to this archiver to the given archive. + /// + /// + public void Archive(TarArchiveWriter archive) + { + //WriteMetadata(archive); + WriteData(archive); + } + + /// + /// Write an assets metadata file to the given archive + /// + /// + protected void WriteMetadata(TarArchiveWriter archive) + { + StringWriter sw = new StringWriter(); + XmlTextWriter xtw = new XmlTextWriter(sw); + + xtw.Formatting = Formatting.Indented; + xtw.WriteStartDocument(); + + xtw.WriteStartElement("assets"); + + foreach (UUID uuid in m_assets.Keys) + { + AssetBase asset = m_assets[uuid]; + + if (asset != null) + { + xtw.WriteStartElement("asset"); + + string extension = string.Empty; + + if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Metadata.Type)) + { + extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Metadata.Type]; + } + + xtw.WriteElementString("filename", uuid.ToString() + extension); + + xtw.WriteElementString("name", asset.Metadata.Name); + xtw.WriteElementString("description", asset.Metadata.Description); + xtw.WriteElementString("asset-type", asset.Metadata.Type.ToString()); + + xtw.WriteEndElement(); + } + } + + xtw.WriteEndElement(); + + xtw.WriteEndDocument(); + + archive.AddFile("assets.xml", sw.ToString()); + } + + /// + /// Write asset data files to the given archive + /// + /// + protected void WriteData(TarArchiveWriter archive) + { + // It appears that gtar, at least, doesn't need the intermediate directory entries in the tar + //archive.AddDir("assets"); + + foreach (UUID uuid in m_assets.Keys) + { + AssetBase asset = m_assets[uuid]; + + string extension = string.Empty; + + if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Metadata.Type)) + { + extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Metadata.Type]; + } + else + { + m_log.ErrorFormat( + "[ARCHIVER]: Unrecognized asset type {0} with uuid {1}. This asset will be saved but not reloaded", + asset.Metadata.Type, asset.Metadata.ID); + } + + archive.AddFile( + ArchiveConstants.ASSETS_PATH + uuid.ToString() + extension, + asset.Data); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs new file mode 100644 index 0000000..f9909d9 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsDearchiver.cs @@ -0,0 +1,184 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Dearchives assets + /// + public class AssetsDearchiver + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); + + /// + /// Store for asset data we received before we get the metadata + /// + protected Dictionary m_assetDataAwaitingMetadata = new Dictionary(); + + /// + /// Asset metadata. Is null if asset metadata isn't yet available. + /// + protected Dictionary m_metadata; + + /// + /// Cache to which dearchived assets will be added + /// + protected IAssetCache m_cache; + + public AssetsDearchiver(IAssetCache cache) + { + m_cache = cache; + } + + /// + /// Add asset data to the dearchiver + /// + /// + /// + public void AddAssetData(string assetFilename, byte[] data) + { + if (null == m_metadata) + { + m_assetDataAwaitingMetadata[assetFilename] = data; + } + else + { + ResolveAssetData(assetFilename, data); + } + } + + /// + /// Add asset metadata xml + /// + /// + public void AddAssetMetadata(string xml) + { + m_metadata = new Dictionary(); + + StringReader sr = new StringReader(xml); + XmlTextReader reader = new XmlTextReader(sr); + + reader.ReadStartElement("assets"); + reader.Read(); + + while (reader.Name.Equals("asset")) + { + reader.Read(); + + AssetMetadata metadata = new AssetMetadata(); + + string filename = reader.ReadElementString("filename"); + m_log.DebugFormat("[DEARCHIVER]: Reading node {0}", filename); + + metadata.Name = reader.ReadElementString("name"); + metadata.Description = reader.ReadElementString("description"); + metadata.AssetType = Convert.ToSByte(reader.ReadElementString("asset-type")); + + m_metadata[filename] = metadata; + + // Read asset end tag + reader.ReadEndElement(); + + reader.Read(); + } + + m_log.DebugFormat("[DEARCHIVER]: Resolved {0} items of asset metadata", m_metadata.Count); + + ResolvePendingAssetData(); + } + + /// + /// Resolve asset data that we collected before receiving the metadata + /// + protected void ResolvePendingAssetData() + { + foreach (string filename in m_assetDataAwaitingMetadata.Keys) + { + ResolveAssetData(filename, m_assetDataAwaitingMetadata[filename]); + } + } + + /// + /// Resolve a new piece of asset data against stored metadata + /// + /// + /// + protected void ResolveAssetData(string assetPath, byte[] data) + { + // Right now we're nastily obtaining the UUID from the filename + string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); + + if (m_metadata.ContainsKey(filename)) + { + AssetMetadata metadata = m_metadata[filename]; + + if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(metadata.AssetType)) + { + string extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[metadata.AssetType]; + filename = filename.Remove(filename.Length - extension.Length); + } + + m_log.DebugFormat("[ARCHIVER]: Importing asset {0}", filename); + + AssetBase asset = new AssetBase(new UUID(filename), metadata.Name); + asset.Metadata.Description = metadata.Description; + asset.Metadata.Type = metadata.AssetType; + asset.Data = data; + + m_cache.AddAsset(asset); + } + else + { + m_log.ErrorFormat( + "[DEARCHIVER]: Tried to dearchive data with filename {0} without any corresponding metadata", + assetPath); + } + } + + /// + /// Metadata for an asset + /// + protected struct AssetMetadata + { + public string Name; + public string Description; + public sbyte AssetType; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs new file mode 100644 index 0000000..8971b6e --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -0,0 +1,138 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Threading; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Encapsulate the asynchronous requests for the assets required for an archive operation + /// + class AssetsRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// uuids to request + /// + protected ICollection m_uuids; + + /// + /// Callback used when all the assets requested have been received. + /// + protected AssetsRequestCallback m_assetsRequestCallback; + + /// + /// Assets retrieved in this request + /// + protected Dictionary m_assets = new Dictionary(); + + /// + /// Maintain a list of assets that could not be found. This will be passed back to the requester. + /// + protected List m_notFoundAssetUuids = new List(); + + /// + /// Record the number of asset replies required so we know when we've finished + /// + private int m_repliesRequired; + + /// + /// Asset cache used to request the assets + /// + protected IAssetCache m_assetCache; + + protected internal AssetsRequest(ICollection uuids, IAssetCache assetCache, AssetsRequestCallback assetsRequestCallback) + { + m_uuids = uuids; + m_assetsRequestCallback = assetsRequestCallback; + m_assetCache = assetCache; + m_repliesRequired = uuids.Count; + } + + protected internal void Execute() + { + // We can stop here if there are no assets to fetch + if (m_repliesRequired == 0) + m_assetsRequestCallback(m_assets, m_notFoundAssetUuids); + + foreach (UUID uuid in m_uuids) + { + m_assetCache.GetAsset(uuid, AssetRequestCallback, true); + } + } + + /// + /// Called back by the asset cache when it has the asset + /// + /// + /// + public void AssetRequestCallback(UUID assetID, AssetBase asset) + { + if (asset != null) + m_assets[assetID] = asset; + else + m_notFoundAssetUuids.Add(assetID); + + //m_log.DebugFormat( + // "[ARCHIVER]: Received {0} assets and notification of {1} missing assets", m_assets.Count, m_notFoundAssetUuids.Count); + + if (m_assets.Count + m_notFoundAssetUuids.Count == m_repliesRequired) + { + // We want to stop using the asset cache thread asap as we now need to do the actual work of producing the archive + Thread newThread = new Thread(PerformAssetsRequestCallback); + newThread.Name = "OpenSimulator archiving thread post assets receipt"; + newThread.Start(); + } + } + + /// + /// Perform the callback on the original requester of the assets + /// + protected void PerformAssetsRequestCallback() + { + try + { + m_assetsRequestCallback(m_assets, m_notFoundAssetUuids); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ARCHIVER]: Terminating archive creation since asset requster callback failed with {0}", e); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/RegionSettingsSerializer.cs b/OpenSim/Region/CoreModules/World/Archiver/RegionSettingsSerializer.cs new file mode 100644 index 0000000..2580316 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/RegionSettingsSerializer.cs @@ -0,0 +1,258 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Text; +using System.Xml; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Serialize and deserialize region settings for an archive file format. + /// + /// We didn't simply use automatic .NET serializagion for OpenSim.Framework.RegionSettings since this is really + /// a file format rather than an object serialization. + /// TODO: However, we could still have used separate non-framework classes here to read and write the xml + /// automatically rather than laboriously doing it by hand using XmlTextReader and Writer. Should switch to this + /// in the future. + public class RegionSettingsSerializer + { + protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); + + /// + /// Deserialize region settings + /// + /// + /// + /// + public static RegionSettings Deserialize(byte[] serializedSettings) + { + return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length)); + } + + /// + /// Deserialize region settings + /// + /// + /// + /// + public static RegionSettings Deserialize(string serializedSettings) + { + RegionSettings settings = new RegionSettings(); + + StringReader sr = new StringReader(serializedSettings); + XmlTextReader xtr = new XmlTextReader(sr); + + xtr.ReadStartElement("RegionSettings"); + + xtr.ReadStartElement("General"); + + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + switch (xtr.Name) + { + case "AllowDamage": + settings.AllowDamage = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "AllowLandResell": + settings.AllowLandResell = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "AllowLandJoinDivide": + settings.AllowLandJoinDivide = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "BlockFly": + settings.BlockFly = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "BlockLandShowInSearch": + settings.BlockShowInSearch = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "BlockTerraform": + settings.BlockTerraform = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "DisableCollisions": + settings.DisableCollisions = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "DisablePhysics": + settings.DisablePhysics = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "DisableScripts": + settings.DisableScripts = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "MaturityRating": + settings.Maturity = int.Parse(xtr.ReadElementContentAsString()); + break; + case "RestrictPushing": + settings.RestrictPushing = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "AgentLimit": + settings.AgentLimit = int.Parse(xtr.ReadElementContentAsString()); + break; + case "ObjectBonus": + settings.ObjectBonus = double.Parse(xtr.ReadElementContentAsString()); + break; + } + } + + xtr.ReadEndElement(); + xtr.ReadStartElement("GroundTextures"); + + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + switch (xtr.Name) + { + case "Texture1": + settings.TerrainTexture1 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "Texture2": + settings.TerrainTexture2 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "Texture3": + settings.TerrainTexture3 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "Texture4": + settings.TerrainTexture4 = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowSW": + settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowNW": + settings.Elevation1NW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowSE": + settings.Elevation1SE = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationLowNE": + settings.Elevation1NE = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighSW": + settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighNW": + settings.Elevation2NW = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighSE": + settings.Elevation2SE = double.Parse(xtr.ReadElementContentAsString()); + break; + case "ElevationHighNE": + settings.Elevation2NE = double.Parse(xtr.ReadElementContentAsString()); + break; + } + } + + xtr.ReadEndElement(); + xtr.ReadStartElement("Terrain"); + + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + switch (xtr.Name) + { + case "WaterHeight": + settings.WaterHeight = double.Parse(xtr.ReadElementContentAsString()); + break; + case "TerrainRaiseLimit": + settings.TerrainRaiseLimit = double.Parse(xtr.ReadElementContentAsString()); + break; + case "TerrainLowerLimit": + settings.TerrainLowerLimit = double.Parse(xtr.ReadElementContentAsString()); + break; + case "UseEstateSun": + settings.UseEstateSun = bool.Parse(xtr.ReadElementContentAsString()); + break; + case "FixedSun": + settings.FixedSun = bool.Parse(xtr.ReadElementContentAsString()); + break; + } + } + + xtr.Close(); + sr.Close(); + + return settings; + } + + public static string Serialize(RegionSettings settings) + { + StringWriter sw = new StringWriter(); + XmlTextWriter xtw = new XmlTextWriter(sw); + xtw.Formatting = Formatting.Indented; + xtw.WriteStartDocument(); + + xtw.WriteStartElement("RegionSettings"); + + xtw.WriteStartElement("General"); + xtw.WriteElementString("AllowDamage", settings.AllowDamage.ToString()); + xtw.WriteElementString("AllowLandResell", settings.AllowLandResell.ToString()); + xtw.WriteElementString("AllowLandJoinDivide", settings.AllowLandJoinDivide.ToString()); + xtw.WriteElementString("BlockFly", settings.BlockFly.ToString()); + xtw.WriteElementString("BlockLandShowInSearch", settings.BlockShowInSearch.ToString()); + xtw.WriteElementString("BlockTerraform", settings.BlockTerraform.ToString()); + xtw.WriteElementString("DisableCollisions", settings.DisableCollisions.ToString()); + xtw.WriteElementString("DisablePhysics", settings.DisablePhysics.ToString()); + xtw.WriteElementString("DisableScripts", settings.DisableScripts.ToString()); + xtw.WriteElementString("MaturityRating", settings.Maturity.ToString()); + xtw.WriteElementString("RestrictPushing", settings.RestrictPushing.ToString()); + xtw.WriteElementString("AgentLimit", settings.AgentLimit.ToString()); + xtw.WriteElementString("ObjectBonus", settings.ObjectBonus.ToString()); + xtw.WriteEndElement(); + + xtw.WriteStartElement("GroundTextures"); + xtw.WriteElementString("Texture1", settings.TerrainTexture1.ToString()); + xtw.WriteElementString("Texture2", settings.TerrainTexture2.ToString()); + xtw.WriteElementString("Texture3", settings.TerrainTexture3.ToString()); + xtw.WriteElementString("Texture4", settings.TerrainTexture4.ToString()); + xtw.WriteElementString("ElevationLowSW", settings.Elevation1SW.ToString()); + xtw.WriteElementString("ElevationLowNW", settings.Elevation1NW.ToString()); + xtw.WriteElementString("ElevationLowSE", settings.Elevation1SE.ToString()); + xtw.WriteElementString("ElevationLowNE", settings.Elevation1NE.ToString()); + xtw.WriteElementString("ElevationHighSW", settings.Elevation2SW.ToString()); + xtw.WriteElementString("ElevationHighNW", settings.Elevation2NW.ToString()); + xtw.WriteElementString("ElevationHighSE", settings.Elevation2SE.ToString()); + xtw.WriteElementString("ElevationHighNE", settings.Elevation2NE.ToString()); + xtw.WriteEndElement(); + + xtw.WriteStartElement("Terrain"); + xtw.WriteElementString("WaterHeight", settings.WaterHeight.ToString()); + xtw.WriteElementString("TerrainRaiseLimit", settings.TerrainRaiseLimit.ToString()); + xtw.WriteElementString("TerrainLowerLimit", settings.TerrainLowerLimit.ToString()); + xtw.WriteElementString("UseEstateSun", settings.UseEstateSun.ToString()); + xtw.WriteElementString("FixedSun", settings.FixedSun.ToString()); + // XXX: Need to expose interface to get sun phase information from sun module + // xtw.WriteStartElement("SunPhase", + xtw.WriteEndElement(); + + xtw.WriteEndElement(); + + xtw.Close(); + sw.Close(); + + return sw.ToString(); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs new file mode 100644 index 0000000..506d770 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs @@ -0,0 +1,195 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Reflection; +using System.Text; +using log4net; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Temporary code to do the bare minimum required to read a tar archive for our purposes + /// + public class TarArchiveReader + { + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public enum TarEntryType + { + TYPE_UNKNOWN = 0, + TYPE_NORMAL_FILE = 1, + TYPE_HARD_LINK = 2, + TYPE_SYMBOLIC_LINK = 3, + TYPE_CHAR_SPECIAL = 4, + TYPE_BLOCK_SPECIAL = 5, + TYPE_DIRECTORY = 6, + TYPE_FIFO = 7, + TYPE_CONTIGUOUS_FILE = 8, + } + + protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); + + /// + /// Binary reader for the underlying stream + /// + protected BinaryReader m_br; + + /// + /// Used to trim off null chars + /// + protected char[] m_nullCharArray = new char[] { '\0' }; + + /// + /// Generate a tar reader which reads from the given stream. + /// + /// + public TarArchiveReader(Stream s) + { + m_br = new BinaryReader(s); + } + + /// + /// Read the next entry in the tar file. + /// + /// + /// the data for the entry. Returns null if there are no more entries + public byte[] ReadEntry(out string filePath, out TarEntryType entryType) + { + filePath = String.Empty; + entryType = TarEntryType.TYPE_UNKNOWN; + TarHeader header = ReadHeader(); + + if (null == header) + return null; + + entryType = header.EntryType; + filePath = header.FilePath; + byte[] data = m_br.ReadBytes(header.FileSize); + + //m_log.DebugFormat("[TAR ARCHIVE READER]: filePath {0}, fileSize {1}", filePath, header.FileSize); + + // Read the rest of the empty padding in the 512 byte block + if (header.FileSize % 512 != 0) + { + int paddingLeft = 512 - (header.FileSize % 512); + + //m_log.DebugFormat("[TAR ARCHIVE READER]: Reading {0} padding bytes", paddingLeft); + + m_br.ReadBytes(paddingLeft); + } + + return data; + } + + /// + /// Read the next 512 byte chunk of data as a tar header. + /// + /// A tar header struct. null if we have reached the end of the archive. + protected TarHeader ReadHeader() + { + byte[] header = m_br.ReadBytes(512); + + // If we've reached the end of the archive we'll be in null block territory, which means + // the next byte will be 0 + if (header[0] == 0) + return null; + + TarHeader tarHeader = new TarHeader(); + + tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100); + tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray); + tarHeader.FileSize = ConvertOctalBytesToDecimal(header, 124, 11); + + switch (header[156]) + { + case 0: + tarHeader.EntryType = TarEntryType.TYPE_NORMAL_FILE; + break; + case (byte)'0': + tarHeader.EntryType = TarEntryType.TYPE_NORMAL_FILE; + break; + case (byte)'1': + tarHeader.EntryType = TarEntryType.TYPE_HARD_LINK; + break; + case (byte)'2': + tarHeader.EntryType = TarEntryType.TYPE_SYMBOLIC_LINK; + break; + case (byte)'3': + tarHeader.EntryType = TarEntryType.TYPE_CHAR_SPECIAL; + break; + case (byte)'4': + tarHeader.EntryType = TarEntryType.TYPE_BLOCK_SPECIAL; + break; + case (byte)'5': + tarHeader.EntryType = TarEntryType.TYPE_DIRECTORY; + break; + case (byte)'6': + tarHeader.EntryType = TarEntryType.TYPE_FIFO; + break; + case (byte)'7': + tarHeader.EntryType = TarEntryType.TYPE_CONTIGUOUS_FILE; + break; + } + + return tarHeader; + } + + public void Close() + { + m_br.Close(); + } + + /// + /// Convert octal bytes to a decimal representation + /// + /// + /// + public static int ConvertOctalBytesToDecimal(byte[] bytes, int startIndex, int count) + { + string oString = m_asciiEncoding.GetString(bytes, startIndex, count); + + int d = 0; + + foreach (char c in oString) + { + d <<= 3; + d |= c - '0'; + } + + return d; + } + } + + public class TarHeader + { + public string FilePath; + public int FileSize; + public TarArchiveReader.TarEntryType EntryType; + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs new file mode 100644 index 0000000..437939e --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveWriter.cs @@ -0,0 +1,202 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Reflection; +using log4net; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Temporary code to produce a tar archive in tar v7 format + /// + public class TarArchiveWriter + { + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Dictionary m_files = new Dictionary(); + + protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); + + /// + /// Add a directory to the tar archive. We can only handle one path level right now! + /// + /// + public void AddDir(string dirName) + { + // Directories are signalled by a final / + if (!dirName.EndsWith("/")) + dirName += "/"; + + AddFile(dirName, new byte[0]); + } + + /// + /// Add a file to the tar archive + /// + /// + /// + public void AddFile(string filePath, string data) + { + AddFile(filePath, m_asciiEncoding.GetBytes(data)); + } + + /// + /// Add a file to the tar archive + /// + /// + /// + public void AddFile(string filePath, byte[] data) + { + m_files[filePath] = data; + } + + /// + /// Write the raw tar archive data to a stream. The stream will be closed on completion. + /// + /// Stream to which to write the data + /// + public void WriteTar(Stream s) + { + BinaryWriter bw = new BinaryWriter(s); + + foreach (string filePath in m_files.Keys) + { + byte[] header = new byte[512]; + byte[] data = m_files[filePath]; + + // file path field (100) + byte[] nameBytes = m_asciiEncoding.GetBytes(filePath); + int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length; + Array.Copy(nameBytes, header, nameSize); + + // file mode (8) + byte[] modeBytes = m_asciiEncoding.GetBytes("0000777"); + Array.Copy(modeBytes, 0, header, 100, 7); + + // owner user id (8) + byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764"); + Array.Copy(ownerIdBytes, 0, header, 108, 7); + + // group user id (8) + byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764"); + Array.Copy(groupIdBytes, 0, header, 116, 7); + + // file size in bytes (12) + int fileSize = data.Length; + //m_log.DebugFormat("[TAR ARCHIVE WRITER]: File size of {0} is {1}", filePath, fileSize); + + byte[] fileSizeBytes = ConvertDecimalToPaddedOctalBytes(fileSize, 11); + + Array.Copy(fileSizeBytes, 0, header, 124, 11); + + // last modification time (12) + byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332"); + Array.Copy(lastModTimeBytes, 0, header, 136, 11); + + // link indicator (1) + //header[156] = m_asciiEncoding.GetBytes("0")[0]; + if (filePath.EndsWith("/")) + { + header[156] = m_asciiEncoding.GetBytes("5")[0]; + } + else + { + header[156] = 0; + } + + Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7); + Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7); + + // check sum for header block (8) [calculated last] + Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8); + + int checksum = 0; + foreach (byte b in header) + { + checksum += b; + } + + //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Decimal header checksum is {0}", checksum); + + byte[] checkSumBytes = ConvertDecimalToPaddedOctalBytes(checksum, 6); + + Array.Copy(checkSumBytes, 0, header, 148, 6); + + header[154] = 0; + + // Write out header + bw.Write(header); + + // Write out data + bw.Write(data); + + if (data.Length % 512 != 0) + { + int paddingRequired = 512 - (data.Length % 512); + + //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Padding data with {0} bytes", paddingRequired); + + byte[] padding = new byte[paddingRequired]; + bw.Write(padding); + } + } + + //m_log.Debug("[TAR ARCHIVE WRITER]: Writing final consecutive 0 blocks"); + + // Write two consecutive 0 blocks to end the archive + byte[] finalZeroPadding = new byte[1024]; + bw.Write(finalZeroPadding); + + bw.Flush(); + bw.Close(); + } + + public static byte[] ConvertDecimalToPaddedOctalBytes(int d, int padding) + { + string oString = ""; + + while (d > 0) + { + oString = Convert.ToString((byte)'0' + d & 7) + oString; + d >>= 3; + } + + while (oString.Length < padding) + { + oString = "0" + oString; + } + + byte[] oBytes = m_asciiEncoding.GetBytes(oString); + + return oBytes; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs new file mode 100644 index 0000000..a14e0f6 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -0,0 +1,188 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Threading; +using NUnit.Framework; +using NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.World.Archiver; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.CoreModules.World.Archiver.Tests +{ + [TestFixture] + public class ArchiverTests + { + private EventWaitHandle m_waitHandle = new AutoResetEvent(false); + + private void SaveCompleted(string errorMessage) + { + m_waitHandle.Set(); + } + + /// + /// Test saving a V0.2 OpenSim Region Archive. + /// + [Test] + public void TestSaveOarV0p2() + { + log4net.Config.XmlConfigurator.Configure(); + + ArchiverModule archiverModule = new ArchiverModule(); + SerialiserModule serialiserModule = new SerialiserModule(); + TerrainModule terrainModule = new TerrainModule(); + + Scene scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); + + SceneObjectPart part1; + + // Create and add prim 1 + { + string partName = "My Little Pony"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000015"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); + + part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; + + scene.AddNewSceneObject(new SceneObjectGroup(part1), false); + } + + SceneObjectPart part2; + + // Create and add prim 2 + { + string partName = "Action Man"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000016"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); + Vector3 groupPosition = new Vector3(90, 80, 70); + Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); + Vector3 offsetPosition = new Vector3(20, 25, 30); + + part2 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part2.Name = partName; + + scene.AddNewSceneObject(new SceneObjectGroup(part2), false); + } + + MemoryStream archiveWriteStream = new MemoryStream(); + + scene.EventManager.OnOarFileSaved += SaveCompleted; + archiverModule.ArchiveRegion(archiveWriteStream); + m_waitHandle.WaitOne(60000, true); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + bool gotControlFile = false; + bool gotObject1File = false; + bool gotObject2File = false; + string expectedObject1FileName = string.Format( + "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", + part1.Name, + Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), + part1.UUID); + string expectedObject2FileName = string.Format( + "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", + part2.Name, + Math.Round(part2.GroupPosition.X), Math.Round(part2.GroupPosition.Y), Math.Round(part2.GroupPosition.Z), + part2.UUID); + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + if (ArchiveConstants.CONTROL_FILE_PATH == filePath) + { + gotControlFile = true; + } + else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) + { + string fileName = filePath.Remove(0, ArchiveConstants.OBJECTS_PATH.Length); + + if (fileName.StartsWith(part1.Name)) + { + Assert.That(fileName, Is.EqualTo(expectedObject1FileName)); + gotObject1File = true; + } + else if (fileName.StartsWith(part2.Name)) + { + Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); + gotObject2File = true; + } + } + } + + Assert.That(gotControlFile, Is.True, "No control file in archive"); + Assert.That(gotObject1File, Is.True, "No object1 file in archive"); + Assert.That(gotObject2File, Is.True, "No object2 file in archive"); + + // TODO: Test presence of more files and contents of files. + } + + /// + /// Test loading a V0.2 OpenSim Region Archive. Does not yet do what it says on the tin. + /// + [Test] + public void TestLoadOarV0p2() + { + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(); + + tar.AddFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile()); + tar.WriteTar(archiveWriteStream); + + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + ArchiverModule archiverModule = new ArchiverModule(); + + Scene scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule); + + archiverModule.DearchiveRegion(archiveReadStream); + + // TODO: Okay, so nothing is tested yet apart from the fact that it doesn't blow up + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs new file mode 100644 index 0000000..8b15308 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -0,0 +1,1012 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Threading; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + public class EstateManagementModule : IEstateModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private delegate void LookupUUIDS(List uuidLst); + + private Scene m_scene; + + private EstateTerrainXferHandler TerrainUploader = null; + + #region Packet Data Responders + + private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) + { + uint sun = 0; + + if (!m_scene.RegionInfo.EstateSettings.UseGlobalTime) + sun=(uint)(m_scene.RegionInfo.EstateSettings.SunPosition*1024.0) + 0x1800; + UUID estateOwner; + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + estateOwner = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + estateOwner = m_scene.RegionInfo.MasterAvatarAssignedUUID; + + if (m_scene.Permissions.IsGod(remote_client.AgentId)) + estateOwner = remote_client.AgentId; + + remote_client.SendDetailedEstateData(invoice, + m_scene.RegionInfo.EstateSettings.EstateName, + m_scene.RegionInfo.EstateSettings.EstateID, + m_scene.RegionInfo.EstateSettings.ParentEstateID, + GetEstateFlags(), + sun, + m_scene.RegionInfo.RegionSettings.Covenant, + m_scene.RegionInfo.EstateSettings.AbuseEmail, + estateOwner); + + remote_client.SendEstateManagersList(invoice, + m_scene.RegionInfo.EstateSettings.EstateManagers, + m_scene.RegionInfo.EstateSettings.EstateID); + + remote_client.SendBannedUserList(invoice, + m_scene.RegionInfo.EstateSettings.EstateBans, + m_scene.RegionInfo.EstateSettings.EstateID); + } + + private void estateSetRegionInfoHandler(bool blockTerraform, bool noFly, bool allowDamage, bool blockLandResell, int maxAgents, float objectBonusFactor, + int matureLevel, bool restrictPushObject, bool allowParcelChanges) + { + if (blockTerraform) + m_scene.RegionInfo.RegionSettings.BlockTerraform = true; + else + m_scene.RegionInfo.RegionSettings.BlockTerraform = false; + + if (noFly) + m_scene.RegionInfo.RegionSettings.BlockFly = true; + else + m_scene.RegionInfo.RegionSettings.BlockFly = false; + + if (allowDamage) + m_scene.RegionInfo.RegionSettings.AllowDamage = true; + else + m_scene.RegionInfo.RegionSettings.AllowDamage = false; + + if (blockLandResell) + m_scene.RegionInfo.RegionSettings.AllowLandResell = false; + else + m_scene.RegionInfo.RegionSettings.AllowLandResell = true; + + m_scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; + + m_scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; + + if (matureLevel <= 13) + m_scene.RegionInfo.RegionSettings.Maturity = 0; + else + m_scene.RegionInfo.RegionSettings.Maturity = 1; + + if (restrictPushObject) + m_scene.RegionInfo.RegionSettings.RestrictPushing = true; + else + m_scene.RegionInfo.RegionSettings.RestrictPushing = false; + + if (allowParcelChanges) + m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide = true; + else + m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide = false; + + m_scene.RegionInfo.RegionSettings.Save(); + + sendRegionInfoPacketToAll(); + } + + public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int corner, UUID texture) + { + if (texture == UUID.Zero) + return; + + switch (corner) + { + case 0: + m_scene.RegionInfo.RegionSettings.TerrainTexture1 = texture; + break; + case 1: + m_scene.RegionInfo.RegionSettings.TerrainTexture2 = texture; + break; + case 2: + m_scene.RegionInfo.RegionSettings.TerrainTexture3 = texture; + break; + case 3: + m_scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; + break; + } + m_scene.RegionInfo.RegionSettings.Save(); + } + + public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue) + { + switch (corner) + { + case 0: + m_scene.RegionInfo.RegionSettings.Elevation1SW = lowValue; + m_scene.RegionInfo.RegionSettings.Elevation2SW = highValue; + break; + case 1: + m_scene.RegionInfo.RegionSettings.Elevation1NW = lowValue; + m_scene.RegionInfo.RegionSettings.Elevation2NW = highValue; + break; + case 2: + m_scene.RegionInfo.RegionSettings.Elevation1SE = lowValue; + m_scene.RegionInfo.RegionSettings.Elevation2SE = highValue; + break; + case 3: + m_scene.RegionInfo.RegionSettings.Elevation1NE = lowValue; + m_scene.RegionInfo.RegionSettings.Elevation2NE = highValue; + break; + } + m_scene.RegionInfo.RegionSettings.Save(); + } + + private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) + { + sendRegionHandshakeToAll(); + } + + public void setRegionTerrainSettings(float WaterHeight, + float TerrainRaiseLimit, float TerrainLowerLimit, + bool UseEstateSun, bool UseFixedSun, float SunHour, + bool UseGlobal, bool EstateFixedSun, float EstateSunHour) + { + // Water Height + m_scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight; + + // Terraforming limits + m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit = TerrainRaiseLimit; + m_scene.RegionInfo.RegionSettings.TerrainLowerLimit = TerrainLowerLimit; + + // Time of day / fixed sun + m_scene.RegionInfo.RegionSettings.UseEstateSun = UseEstateSun; + m_scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun; + m_scene.RegionInfo.RegionSettings.SunPosition = SunHour; + + m_scene.EventManager.TriggerEstateToolsTimeUpdate(m_scene.RegionInfo.RegionHandle, UseFixedSun, UseEstateSun, SunHour); + + //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString()); + //m_log.Debug("[ESTATE]: SunHour: " + SunHour.ToString()); + + sendRegionInfoPacketToAll(); + m_scene.RegionInfo.RegionSettings.Save(); + } + + private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) + { + m_scene.Restart(timeInSeconds); + } + + private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID) + { + m_scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; + m_scene.RegionInfo.RegionSettings.Save(); + } + + private void handleEstateAccessDeltaRequest(IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user) + { + // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc. + + if (user == m_scene.RegionInfo.EstateSettings.EstateOwner) + return; // never process EO + if (user == m_scene.RegionInfo.MasterAvatarAssignedUUID) + return; // never process owner + + switch (estateAccessType) + { + case 64: + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) + { + EstateBan[] banlistcheck = m_scene.RegionInfo.EstateSettings.EstateBans; + + bool alreadyInList = false; + + for (int i = 0; i < banlistcheck.Length; i++) + { + if (user == banlistcheck[i].bannedUUID) + { + alreadyInList = true; + break; + } + + } + if (!alreadyInList) + { + + EstateBan item = new EstateBan(); + + item.bannedUUID = user; + item.estateID = m_scene.RegionInfo.EstateSettings.EstateID; + item.bannedIP = "0.0.0.0"; + item.bannedIPHostMask = "0.0.0.0"; + + m_scene.RegionInfo.EstateSettings.AddBan(item); + m_scene.RegionInfo.EstateSettings.Save(); + + ScenePresence s = m_scene.GetScenePresence(user); + if (s != null) + { + if (!s.IsChildAgent) + { + s.ControllingClient.SendTeleportLocationStart(); + m_scene.TeleportClientHome(user, s.ControllingClient); + } + } + + } + else + { + remote_client.SendAlertMessage("User is already on the region ban list"); + } + //m_scene.RegionInfo.regionBanlist.Add(Manager(user); + remote_client.SendBannedUserList(invoice, m_scene.RegionInfo.EstateSettings.EstateBans, m_scene.RegionInfo.EstateSettings.EstateID); + } + else + { + remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); + } + break; + case 128: + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) + { + EstateBan[] banlistcheck = m_scene.RegionInfo.EstateSettings.EstateBans; + + bool alreadyInList = false; + EstateBan listitem = null; + + for (int i = 0; i < banlistcheck.Length; i++) + { + if (user == banlistcheck[i].bannedUUID) + { + alreadyInList = true; + listitem = banlistcheck[i]; + break; + } + + } + if (alreadyInList && listitem != null) + { + m_scene.RegionInfo.EstateSettings.RemoveBan(listitem.bannedUUID); + m_scene.RegionInfo.EstateSettings.Save(); + } + else + { + remote_client.SendAlertMessage("User is not on the region ban list"); + } + //m_scene.RegionInfo.regionBanlist.Add(Manager(user); + remote_client.SendBannedUserList(invoice, m_scene.RegionInfo.EstateSettings.EstateBans, m_scene.RegionInfo.EstateSettings.EstateID); + } + else + { + remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); + } + break; + case 256: + + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) + { + m_scene.RegionInfo.EstateSettings.AddEstateManager(user); + m_scene.RegionInfo.EstateSettings.Save(); + remote_client.SendEstateManagersList(invoice, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID); + } + else + { + remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); + } + + break; + case 512: + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) + { + m_scene.RegionInfo.EstateSettings.RemoveEstateManager(user); + m_scene.RegionInfo.EstateSettings.Save(); + + remote_client.SendEstateManagersList(invoice, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID); + } + else + { + remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); + } + break; + + default: + + m_log.ErrorFormat("EstateOwnerMessage: Unknown EstateAccessType requested in estateAccessDelta: {0}", estateAccessType.ToString()); + break; + } + } + + private void SendSimulatorBlueBoxMessage( + IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) + { + IDialogModule dm = m_scene.RequestModuleInterface(); + + if (dm != null) + dm.SendNotificationToUsersInRegion(senderID, senderName, message); + } + + private void SendEstateBlueBoxMessage( + IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) + { + IDialogModule dm = m_scene.RequestModuleInterface(); + + if (dm != null) + dm.SendNotificationToUsersInEstate(senderID, senderName, message); + } + + private void handleEstateDebugRegionRequest(IClientAPI remote_client, UUID invoice, UUID senderID, bool scripted, bool collisionEvents, bool physics) + { + if (physics) + m_scene.RegionInfo.RegionSettings.DisablePhysics = true; + else + m_scene.RegionInfo.RegionSettings.DisablePhysics = false; + + if (scripted) + m_scene.RegionInfo.RegionSettings.DisableScripts = true; + else + m_scene.RegionInfo.RegionSettings.DisableScripts = false; + + if (collisionEvents) + m_scene.RegionInfo.RegionSettings.DisableCollisions = true; + else + m_scene.RegionInfo.RegionSettings.DisableCollisions = false; + + + m_scene.RegionInfo.RegionSettings.Save(); + + m_scene.SetSceneCoreDebug(scripted, collisionEvents, physics); + } + + private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) + { + if (prey != UUID.Zero) + { + ScenePresence s = m_scene.GetScenePresence(prey); + if (s != null) + { + s.ControllingClient.SendTeleportLocationStart(); + m_scene.TeleportClientHome(prey, s.ControllingClient); + } + } + } + + private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID) + { + // Get a fresh list that will not change as people get teleported away + List prescences = m_scene.GetScenePresences(); + foreach (ScenePresence p in prescences) + { + if (p.UUID != senderID) + { + // make sure they are still there, we could be working down a long list + ScenePresence s = m_scene.GetScenePresence(p.UUID); + if (s != null) + { + // Also make sure they are actually in the region + if (!s.IsChildAgent) + { + s.ControllingClient.SendTeleportLocationStart(); + m_scene.TeleportClientHome(s.UUID, s.ControllingClient); + } + } + } + } + } + private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) + { + if (TerrainUploader != null) + { + lock (TerrainUploader) + { + if (XferID == TerrainUploader.XferID) + { + remoteClient.OnXferReceive -= TerrainUploader.XferReceive; + remoteClient.OnAbortXfer -= AbortTerrainXferHandler; + TerrainUploader.TerrainUploadDone -= HandleTerrainApplication; + + TerrainUploader = null; + remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); + } + } + } + + } + private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) + { + lock (TerrainUploader) + { + remoteClient.OnXferReceive -= TerrainUploader.XferReceive; + remoteClient.OnAbortXfer -= AbortTerrainXferHandler; + TerrainUploader.TerrainUploadDone -= HandleTerrainApplication; + + TerrainUploader = null; + } + remoteClient.SendAlertMessage("Terrain Upload Complete. Loading...."); + OpenSim.Region.CoreModules.World.Terrain.ITerrainModule terr = m_scene.RequestModuleInterface(); + + if (terr != null) + { + m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + m_scene.RegionInfo.RegionName); + if (System.IO.File.Exists(Util.dataDir() + "/terrain.raw")) + { + System.IO.File.Delete(Util.dataDir() + "/terrain.raw"); + } + try + { + System.IO.FileStream input = new System.IO.FileStream(Util.dataDir() + "/terrain.raw", System.IO.FileMode.CreateNew); + input.Write(terrainData, 0, terrainData.Length); + input.Close(); + } + catch (System.IO.IOException e) + { + m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); + remoteClient.SendAlertMessage("There was an IO Exception loading your terrain. Please check free space"); + + return; + } + catch (System.Security.SecurityException e) + { + m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); + remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive"); + + return; + } + catch (System.UnauthorizedAccessException e) + { + m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); + remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive"); + + return; + } + + + + + try + { + terr.LoadFromFile(Util.dataDir() + "/terrain.raw"); + remoteClient.SendAlertMessage("Your terrain was loaded. Give it a minute or two to apply"); + } + catch (Exception e) + { + m_log.ErrorFormat("[TERRAIN]: Error loading a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); + remoteClient.SendAlertMessage("There was a general error loading your terrain. Please fix the terrain file and try again"); + } + + } + else + { + remoteClient.SendAlertMessage("Unable to apply terrain. Cannot get an instance of the terrain module"); + } + + + + } + + private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) + { + + if (TerrainUploader == null) + { + + TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName); + lock (TerrainUploader) + { + remote_client.OnXferReceive += TerrainUploader.XferReceive; + remote_client.OnAbortXfer += AbortTerrainXferHandler; + TerrainUploader.TerrainUploadDone += HandleTerrainApplication; + } + TerrainUploader.RequestStartXfer(remote_client); + + } + else + { + remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); + } + + } + private void handleTerrainRequest(IClientAPI remote_client, string clientFileName) + { + // Save terrain here + OpenSim.Region.CoreModules.World.Terrain.ITerrainModule terr = m_scene.RequestModuleInterface(); + + if (terr != null) + { + m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + m_scene.RegionInfo.RegionName); + if (System.IO.File.Exists(Util.dataDir() + "/terrain.raw")) + { + System.IO.File.Delete(Util.dataDir() + "/terrain.raw"); + } + terr.SaveToFile(Util.dataDir() + "/terrain.raw"); + + System.IO.FileStream input = new System.IO.FileStream(Util.dataDir() + "/terrain.raw", System.IO.FileMode.Open); + byte[] bdata = new byte[input.Length]; + input.Read(bdata, 0, (int)input.Length); + remote_client.SendAlertMessage("Terrain file written, starting download..."); + m_scene.XferManager.AddNewFile("terrain.raw", bdata); + // Tell client about it + m_log.Warn("[CLIENT]: Sending Terrain to " + remote_client.Name); + remote_client.SendInitiateDownload("terrain.raw", clientFileName); + } + } + + private void HandleRegionInfoRequest(IClientAPI remote_client) + { + RegionInfoForEstateMenuArgs args = new RegionInfoForEstateMenuArgs(); + args.billableFactor = m_scene.RegionInfo.EstateSettings.BillableFactor; + args.estateID = m_scene.RegionInfo.EstateSettings.EstateID; + args.maxAgents = (byte)m_scene.RegionInfo.RegionSettings.AgentLimit; + args.objectBonusFactor = (float)m_scene.RegionInfo.RegionSettings.ObjectBonus; + args.parentEstateID = m_scene.RegionInfo.EstateSettings.ParentEstateID; + args.pricePerMeter = m_scene.RegionInfo.EstateSettings.PricePerMeter; + args.redirectGridX = m_scene.RegionInfo.EstateSettings.RedirectGridX; + args.redirectGridY = m_scene.RegionInfo.EstateSettings.RedirectGridY; + args.regionFlags = GetRegionFlags(); + byte mature = 13; + if (m_scene.RegionInfo.RegionSettings.Maturity == 1) + mature = 21; + args.simAccess = mature; + + args.sunHour = (float)m_scene.RegionInfo.RegionSettings.SunPosition; + args.terrainLowerLimit = (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit; + args.terrainRaiseLimit = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; + args.useEstateSun = m_scene.RegionInfo.RegionSettings.UseEstateSun; + args.waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; + args.simName = m_scene.RegionInfo.RegionName; + + remote_client.SendRegionInfoToEstateMenu(args); + } + + private void HandleEstateCovenantRequest(IClientAPI remote_client) + { + remote_client.SendEstateCovenantInformation(m_scene.RegionInfo.RegionSettings.Covenant); + } + + private void HandleLandStatRequest(int parcelID, uint reportType, uint requestFlags, string filter, IClientAPI remoteClient) + { + Dictionary SceneData = new Dictionary(); + List uuidNameLookupList = new List(); + + if (reportType == 1) + { + SceneData = m_scene.PhysicsScene.GetTopColliders(); + } + else if (reportType == 0) + { + SceneData = m_scene.m_sceneGraph.GetTopScripts(); + } + + List SceneReport = new List(); + lock (SceneData) + { + foreach (uint obj in SceneData.Keys) + { + SceneObjectPart prt = m_scene.GetSceneObjectPart(obj); + if (prt != null) + { + if (prt.ParentGroup != null) + { + SceneObjectGroup sog = prt.ParentGroup; + if (sog != null) + { + LandStatReportItem lsri = new LandStatReportItem(); + lsri.LocationX = sog.AbsolutePosition.X; + lsri.LocationY = sog.AbsolutePosition.Y; + lsri.LocationZ = sog.AbsolutePosition.Z; + lsri.Score = SceneData[obj]; + lsri.TaskID = sog.UUID; + lsri.TaskLocalID = sog.LocalId; + lsri.TaskName = sog.GetPartName(obj); + if (m_scene.CommsManager.UUIDNameCachedTest(sog.OwnerID)) + { + lsri.OwnerName = m_scene.CommsManager.UUIDNameRequestString(sog.OwnerID); + } + else + { + lsri.OwnerName = "waiting"; + lock (uuidNameLookupList) + uuidNameLookupList.Add(sog.OwnerID); + } + + if (filter.Length != 0) + { + if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter))) + { + } + else + { + continue; + } + } + + SceneReport.Add(lsri); + } + } + } + + } + } + remoteClient.SendLandStatReply(reportType, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray()); + + if (uuidNameLookupList.Count > 0) + LookupUUID(uuidNameLookupList); + } + + private void LookupUUIDSCompleted(IAsyncResult iar) + { + LookupUUIDS icon = (LookupUUIDS)iar.AsyncState; + icon.EndInvoke(iar); + } + private void LookupUUID(List uuidLst) + { + LookupUUIDS d = LookupUUIDsAsync; + + d.BeginInvoke(uuidLst, + LookupUUIDSCompleted, + d); + } + private void LookupUUIDsAsync(List uuidLst) + { + UUID[] uuidarr = new UUID[0]; + + lock (uuidLst) + { + uuidarr = uuidLst.ToArray(); + } + + for (int i = 0; i < uuidarr.Length; i++) + { + // string lookupname = m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]); + m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]); + // we drop it. It gets cached though... so we're ready for the next request. + } + } + #endregion + + #region Outgoing Packets + + public void sendRegionInfoPacketToAll() + { + List avatars = m_scene.GetAvatars(); + + for (int i = 0; i < avatars.Count; i++) + { + HandleRegionInfoRequest(avatars[i].ControllingClient); ; + } + } + + public void sendRegionHandshake(IClientAPI remoteClient) + { + RegionHandshakeArgs args = new RegionHandshakeArgs(); + + args.isEstateManager = m_scene.RegionInfo.EstateSettings.IsEstateManager(remoteClient.AgentId); + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && m_scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId) + args.isEstateManager = true; + + args.billableFactor = m_scene.RegionInfo.EstateSettings.BillableFactor; + args.terrainStartHeight0 = (float)m_scene.RegionInfo.RegionSettings.Elevation1SW; + args.terrainHeightRange0 = (float)m_scene.RegionInfo.RegionSettings.Elevation2SW; + args.terrainStartHeight1 = (float)m_scene.RegionInfo.RegionSettings.Elevation1NW; + args.terrainHeightRange1 = (float)m_scene.RegionInfo.RegionSettings.Elevation2NW; + args.terrainStartHeight2 = (float)m_scene.RegionInfo.RegionSettings.Elevation1SE; + args.terrainHeightRange2 = (float)m_scene.RegionInfo.RegionSettings.Elevation2SE; + args.terrainStartHeight3 = (float)m_scene.RegionInfo.RegionSettings.Elevation1NE; + args.terrainHeightRange3 = (float)m_scene.RegionInfo.RegionSettings.Elevation2NE; + byte mature = 13; + if (m_scene.RegionInfo.RegionSettings.Maturity == 1) + mature = 21; + args.simAccess = mature; + args.waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; + + args.regionFlags = GetRegionFlags(); + args.regionName = m_scene.RegionInfo.RegionName; + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + args.SimOwner = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + args.SimOwner = m_scene.RegionInfo.MasterAvatarAssignedUUID; + + // Fudge estate owner + //if (m_scene.Permissions.IsGod(remoteClient.AgentId)) + // args.SimOwner = remoteClient.AgentId; + + args.terrainBase0 = UUID.Zero; + args.terrainBase1 = UUID.Zero; + args.terrainBase2 = UUID.Zero; + args.terrainBase3 = UUID.Zero; + args.terrainDetail0 = m_scene.RegionInfo.RegionSettings.TerrainTexture1; + args.terrainDetail1 = m_scene.RegionInfo.RegionSettings.TerrainTexture2; + args.terrainDetail2 = m_scene.RegionInfo.RegionSettings.TerrainTexture3; + args.terrainDetail3 = m_scene.RegionInfo.RegionSettings.TerrainTexture4; + + remoteClient.SendRegionHandshake(m_scene.RegionInfo,args); + } + + public void sendRegionHandshakeToAll() + { + m_scene.Broadcast(sendRegionHandshake); + } + + public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2) + { + if (parms2 == 0) + { + m_scene.RegionInfo.EstateSettings.UseGlobalTime = true; + m_scene.RegionInfo.EstateSettings.SunPosition = 0.0; + } + else + { + m_scene.RegionInfo.EstateSettings.UseGlobalTime = false; + m_scene.RegionInfo.EstateSettings.SunPosition = (double)(parms2 - 0x1800)/1024.0; + } + + if ((parms1 & 0x00000010) != 0) + m_scene.RegionInfo.EstateSettings.FixedSun = true; + else + m_scene.RegionInfo.EstateSettings.FixedSun = false; + + if ((parms1 & 0x00008000) != 0) + m_scene.RegionInfo.EstateSettings.PublicAccess = true; + else + m_scene.RegionInfo.EstateSettings.PublicAccess = false; + + if ((parms1 & 0x10000000) != 0) + m_scene.RegionInfo.EstateSettings.AllowVoice = true; + else + m_scene.RegionInfo.EstateSettings.AllowVoice = false; + + if ((parms1 & 0x00100000) != 0) + m_scene.RegionInfo.EstateSettings.AllowDirectTeleport = true; + else + m_scene.RegionInfo.EstateSettings.AllowDirectTeleport = false; + + if ((parms1 & 0x00800000) != 0) + m_scene.RegionInfo.EstateSettings.DenyAnonymous = true; + else + m_scene.RegionInfo.EstateSettings.DenyAnonymous = false; + + if ((parms1 & 0x01000000) != 0) + m_scene.RegionInfo.EstateSettings.DenyIdentified = true; + else + m_scene.RegionInfo.EstateSettings.DenyIdentified = false; + + if ((parms1 & 0x02000000) != 0) + m_scene.RegionInfo.EstateSettings.DenyTransacted = true; + else + m_scene.RegionInfo.EstateSettings.DenyTransacted = false; + + if ((parms1 & 0x40000000) != 0) + m_scene.RegionInfo.EstateSettings.DenyMinors = true; + else + m_scene.RegionInfo.EstateSettings.DenyMinors = false; + + m_scene.RegionInfo.EstateSettings.Save(); + + float sun = (float)m_scene.RegionInfo.RegionSettings.SunPosition; + if (m_scene.RegionInfo.RegionSettings.UseEstateSun) + { + sun = (float)m_scene.RegionInfo.EstateSettings.SunPosition; + if (m_scene.RegionInfo.EstateSettings.UseGlobalTime) + sun = m_scene.EventManager.GetSunLindenHour(); + } + + m_scene.EventManager.TriggerEstateToolsTimeUpdate( + m_scene.RegionInfo.RegionHandle, + m_scene.RegionInfo.EstateSettings.FixedSun || + m_scene.RegionInfo.RegionSettings.FixedSun, + m_scene.RegionInfo.RegionSettings.UseEstateSun, sun); + + sendDetailedEstateData(remoteClient, invoice); + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_scene.EventManager.OnNewClient += EventManager_OnNewClient; + m_scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight; + } + + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "EstateManagementModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region Other Functions + + public void changeWaterHeight(float height) + { + setRegionTerrainSettings(height, + (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit, + (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit, + m_scene.RegionInfo.RegionSettings.UseEstateSun, + m_scene.RegionInfo.RegionSettings.FixedSun, + (float)m_scene.RegionInfo.RegionSettings.SunPosition, + m_scene.RegionInfo.EstateSettings.UseGlobalTime, + m_scene.RegionInfo.EstateSettings.FixedSun, + (float)m_scene.RegionInfo.EstateSettings.SunPosition); + + sendRegionInfoPacketToAll(); + } + + #endregion + + private void EventManager_OnNewClient(IClientAPI client) + { + client.OnDetailedEstateDataRequest += sendDetailedEstateData; + client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler; +// client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture; + client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture; + client.OnSetEstateTerrainTextureHeights += setEstateTerrainTextureHeights; + client.OnCommitEstateTerrainTextureRequest += handleCommitEstateTerrainTextureRequest; + client.OnSetRegionTerrainSettings += setRegionTerrainSettings; + client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; + client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; + client.OnEstateChangeInfo += handleEstateChangeInfo; + client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; + client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; + client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; + client.OnEstateDebugRegionRequest += handleEstateDebugRegionRequest; + client.OnEstateTeleportOneUserHomeRequest += handleEstateTeleportOneUserHomeRequest; + client.OnEstateTeleportAllUsersHomeRequest += handleEstateTeleportAllUsersHomeRequest; + client.OnRequestTerrain += handleTerrainRequest; + client.OnUploadTerrain += handleUploadTerrain; + + client.OnRegionInfoRequest += HandleRegionInfoRequest; + client.OnEstateCovenantRequest += HandleEstateCovenantRequest; + client.OnLandStatRequest += HandleLandStatRequest; + sendRegionHandshake(client); + } + + public uint GetRegionFlags() + { + RegionFlags flags = RegionFlags.None; + + // Fully implemented + // + if (m_scene.RegionInfo.RegionSettings.AllowDamage) + flags |= RegionFlags.AllowDamage; + if (m_scene.RegionInfo.RegionSettings.BlockTerraform) + flags |= RegionFlags.BlockTerraform; + if (!m_scene.RegionInfo.RegionSettings.AllowLandResell) + flags |= RegionFlags.BlockLandResell; + if (m_scene.RegionInfo.RegionSettings.DisableCollisions) + flags |= RegionFlags.SkipCollisions; + if (m_scene.RegionInfo.RegionSettings.DisableScripts) + flags |= RegionFlags.SkipScripts; + if (m_scene.RegionInfo.RegionSettings.DisablePhysics) + flags |= RegionFlags.SkipPhysics; + if (m_scene.RegionInfo.RegionSettings.BlockFly) + flags |= RegionFlags.NoFly; + if (m_scene.RegionInfo.RegionSettings.RestrictPushing) + flags |= RegionFlags.RestrictPushObject; + if (m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide) + flags |= RegionFlags.AllowParcelChanges; + if (m_scene.RegionInfo.RegionSettings.BlockShowInSearch) + flags |= (RegionFlags)(1 << 29); + + if (m_scene.RegionInfo.RegionSettings.FixedSun) + flags |= RegionFlags.SunFixed; + if (m_scene.RegionInfo.RegionSettings.Sandbox) + flags |= RegionFlags.Sandbox; + + // Fudge these to always on, so the menu options activate + // + flags |= RegionFlags.AllowLandmark; + flags |= RegionFlags.AllowSetHome; + + // TODO: SkipUpdateInterestList + + // Omitted + // + // Omitted: NullLayer (what is that?) + // Omitted: SkipAgentAction (what does it do?) + + return (uint)flags; + } + + public uint GetEstateFlags() + { + RegionFlags flags = RegionFlags.None; + + if (m_scene.RegionInfo.EstateSettings.FixedSun) + flags |= RegionFlags.SunFixed; + if (m_scene.RegionInfo.EstateSettings.PublicAccess) + flags |= (RegionFlags.PublicAllowed | + RegionFlags.ExternallyVisible); + if (m_scene.RegionInfo.EstateSettings.AllowVoice) + flags |= RegionFlags.AllowVoice; + if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) + flags |= RegionFlags.AllowDirectTeleport; + if (m_scene.RegionInfo.EstateSettings.DenyAnonymous) + flags |= RegionFlags.DenyAnonymous; + if (m_scene.RegionInfo.EstateSettings.DenyIdentified) + flags |= RegionFlags.DenyIdentified; + if (m_scene.RegionInfo.EstateSettings.DenyTransacted) + flags |= RegionFlags.DenyTransacted; + if (m_scene.RegionInfo.EstateSettings.AbuseEmailToEstateOwner) + flags |= RegionFlags.AbuseEmailToEstateOwner; + if (m_scene.RegionInfo.EstateSettings.BlockDwell) + flags |= RegionFlags.BlockDwell; + if (m_scene.RegionInfo.EstateSettings.EstateSkipScripts) + flags |= RegionFlags.EstateSkipScripts; + if (m_scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) + flags |= RegionFlags.ResetHomeOnTeleport; + if (m_scene.RegionInfo.EstateSettings.TaxFree) + flags |= RegionFlags.TaxFree; + if (m_scene.RegionInfo.EstateSettings.DenyMinors) + flags |= (RegionFlags)(1 << 30); + + return (uint)flags; + } + + public bool IsManager(UUID avatarID) + { + if (avatarID == m_scene.RegionInfo.MasterAvatarAssignedUUID) + return true; + if (avatarID == m_scene.RegionInfo.EstateSettings.EstateOwner) + return true; + + List ems = new List(m_scene.RegionInfo.EstateSettings.EstateManagers); + if (ems.Contains(avatarID)) + return true; + + return false; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs new file mode 100644 index 0000000..94a4072 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs @@ -0,0 +1,127 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Scenes; + + +namespace OpenSim.Region.CoreModules.World.Estate +{ + + public class EstateTerrainXferHandler + { + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private AssetBase m_asset; + + public delegate void TerrainUploadComplete(string name, byte[] filedata, IClientAPI remoteClient); + + public event TerrainUploadComplete TerrainUploadDone; + + //private string m_description = String.Empty; + //private string m_name = String.Empty; + //private UUID TransactionID = UUID.Zero; + private sbyte type = 0; + + public ulong mXferID; + private TerrainUploadComplete handlerTerrainUploadDone; + + public EstateTerrainXferHandler(IClientAPI pRemoteClient, string pClientFilename) + { + + m_asset = new AssetBase(); + m_asset.Metadata.FullID = UUID.Zero; + m_asset.Metadata.Type = type; + m_asset.Data = new byte[0]; + m_asset.Metadata.Name = pClientFilename; + m_asset.Metadata.Description = "empty"; + m_asset.Metadata.Local = true; + m_asset.Metadata.Temporary = true; + + } + + public ulong XferID + { + get { return mXferID; } + } + + public void RequestStartXfer(IClientAPI pRemoteClient) + { + mXferID = Util.GetNextXferID(); + pRemoteClient.SendXferRequest(mXferID, m_asset.Metadata.Type, m_asset.Metadata.FullID, 0, Utils.StringToBytes(m_asset.Metadata.Name)); + } + + /// + /// Process transfer data received from the client. + /// + /// + /// + /// + public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + if (mXferID == xferID) + { + if (m_asset.Data.Length > 1) + { + byte[] destinationArray = new byte[m_asset.Data.Length + data.Length]; + Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length); + Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length); + m_asset.Data = destinationArray; + } + else + { + byte[] buffer2 = new byte[data.Length - 4]; + Array.Copy(data, 4, buffer2, 0, data.Length - 4); + m_asset.Data = buffer2; + } + + remoteClient.SendConfirmXfer(xferID, packetID); + + if ((packetID & 0x80000000) != 0) + { + SendCompleteMessage(remoteClient); + + } + } + } + + public void SendCompleteMessage(IClientAPI remoteClient) + { + handlerTerrainUploadDone = TerrainUploadDone; + if (handlerTerrainUploadDone != null) + { + handlerTerrainUploadDone(m_asset.Metadata.Name, m_asset.Data, remoteClient); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs new file mode 100644 index 0000000..41163a0 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs @@ -0,0 +1,188 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Land +{ + public class LandChannel : ILandChannel + { + #region Constants + + //Land types set with flags in ParcelOverlay. + //Only one of these can be used. + public const float BAN_LINE_SAFETY_HIEGHT = 100; + public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000 + public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000 + + //RequestResults (I think these are right, they seem to work): + public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land + public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land + + //ParcelSelectObjects + public const int LAND_SELECT_OBJECTS_GROUP = 4; + public const int LAND_SELECT_OBJECTS_OTHER = 8; + public const int LAND_SELECT_OBJECTS_OWNER = 2; + public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101 + public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100 + public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010 + public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001 + public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011 + public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000 + + //These are other constants. Yay! + public const int START_LAND_LOCAL_ID = 1; + + #endregion + + private readonly Scene m_scene; + private readonly LandManagementModule m_landManagementModule; + + public LandChannel(Scene scene, LandManagementModule landManagementMod) + { + m_scene = scene; + m_landManagementModule = landManagementMod; + } + + #region ILandChannel Members + + + /// + /// Get the land object at the specified point + /// + /// Value between 0 - 256 on the x axis of the point + /// Value between 0 - 256 on the y axis of the point + /// Land object at the point supplied + public ILandObject GetLandObject(float x_float, float y_float) + { + if (m_landManagementModule != null) + { + return m_landManagementModule.GetLandObject(x_float, y_float); + } + ILandObject obj = new LandObject(UUID.Zero, false, m_scene); + obj.landData.Name = "NO LAND"; + return obj; + } + + public ILandObject GetLandObject(int x, int y) + { + if (m_landManagementModule != null) + { + return m_landManagementModule.GetLandObject(x, y); + } + ILandObject obj = new LandObject(UUID.Zero, false, m_scene); + obj.landData.Name = "NO LAND"; + return obj; + } + + public List AllParcels() + { + if (m_landManagementModule != null) + { + return m_landManagementModule.AllParcels(); + } + + return new List(); + } + + public List ParcelsNearPoint(Vector3 position) + { + if (m_landManagementModule != null) + { + return m_landManagementModule.ParcelsNearPoint(position); + } + + return new List(); + } + + public bool IsLandPrimCountTainted() + { + if (m_landManagementModule != null) + { + return m_landManagementModule.IsLandPrimCountTainted(); + } + + return false; + } + + public bool IsForcefulBansAllowed() + { + if (m_landManagementModule != null) + { + return m_landManagementModule.AllowedForcefulBans; + } + + return false; + } + + public void UpdateLandObject(int localID, LandData data) + { + if (m_landManagementModule != null) + { + m_landManagementModule.UpdateLandObject(localID, data); + } + } + public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) + { + if (m_landManagementModule != null) + { + m_landManagementModule.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient); + } + } + + public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) + { + if (m_landManagementModule != null) + { + m_landManagementModule.setParcelObjectMaxOverride(overrideDel); + } + } + + public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) + { + if (m_landManagementModule != null) + { + m_landManagementModule.setSimulatorObjectMaxOverride(overrideDel); + } + } + + public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) + { + if (m_landManagementModule != null) + { + m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs new file mode 100644 index 0000000..6ae6576 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -0,0 +1,1347 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Region.Physics.Manager; +using Caps = OpenSim.Framework.Communications.Capabilities.Caps; + +namespace OpenSim.Region.CoreModules.World.Land +{ + // used for caching + internal class ExtendedLandData { + public LandData landData; + public ulong regionHandle; + public uint x, y; + } + + public class LandManagementModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly string remoteParcelRequestPath = "0009/"; + + private LandChannel landChannel; + private Scene m_scene; + + private readonly int[,] m_landIDList = new int[64, 64]; + private readonly Dictionary m_landList = new Dictionary(); + + private bool m_landPrimCountTainted; + private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; + + private bool m_allowedForcefulBans = true; + + // caches ExtendedLandData + private Cache parcelInfoCache; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + m_landIDList.Initialize(); + landChannel = new LandChannel(scene, this); + + parcelInfoCache = new Cache(); + parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache + parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0); + + m_scene.EventManager.OnParcelPrimCountAdd += AddPrimToLandPrimCounts; + m_scene.EventManager.OnParcelPrimCountUpdate += UpdateLandPrimCounts; + m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(handleAvatarChangingParcel); + m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(handleAnyClientMovement); + m_scene.EventManager.OnValidateLandBuy += handleLandValidationRequest; + m_scene.EventManager.OnLandBuy += handleLandBuyRequest; + m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); + m_scene.EventManager.OnSignificantClientMovement += handleSignificantClientMovement; + m_scene.EventManager.OnObjectBeingRemovedFromScene += RemovePrimFromLandPrimCounts; + + m_scene.EventManager.OnNoticeNoLandDataFromStorage += this.NoLandDataFromStorage; + m_scene.EventManager.OnIncomingLandDataFromStorage += this.IncomingLandObjectsFromStorage; + m_scene.EventManager.OnSetAllowForcefulBan += this.SetAllowedForcefulBans; + m_scene.EventManager.OnRequestParcelPrimCountUpdate += this.PerformParcelPrimCountUpdate; + m_scene.EventManager.OnParcelPrimCountTainted += this.SetPrimsTainted; + m_scene.EventManager.OnRegisterCaps += this.OnRegisterCaps; + + lock (m_scene) + { + m_scene.LandChannel = (ILandChannel) landChannel; + } + } + + void EventManager_OnNewClient(IClientAPI client) + { + //Register some client events + client.OnParcelPropertiesRequest += new ParcelPropertiesRequest(handleParcelPropertiesRequest); + client.OnParcelDivideRequest += new ParcelDivideRequest(handleParcelDivideRequest); + client.OnParcelJoinRequest += new ParcelJoinRequest(handleParcelJoinRequest); + client.OnParcelPropertiesUpdateRequest += new ParcelPropertiesUpdateRequest(handleParcelPropertiesUpdateRequest); + client.OnParcelSelectObjects += new ParcelSelectObjects(handleParcelSelectObjectsRequest); + client.OnParcelObjectOwnerRequest += new ParcelObjectOwnerRequest(handleParcelObjectOwnersRequest); + client.OnParcelAccessListRequest += new ParcelAccessListRequest(handleParcelAccessRequest); + client.OnParcelAccessListUpdateRequest += new ParcelAccessListUpdateRequest(handleParcelAccessUpdateRequest); + client.OnParcelAbandonRequest += new ParcelAbandonRequest(handleParcelAbandonRequest); + client.OnParcelGodForceOwner += new ParcelGodForceOwner(handleParcelGodForceOwner); + client.OnParcelReclaim += new ParcelReclaim(handleParcelReclaim); + client.OnParcelInfoRequest += new ParcelInfoRequest(handleParcelInfo); + client.OnParcelDwellRequest += new ParcelDwellRequest(handleParcelDwell); + if (m_scene.Entities.ContainsKey(client.AgentId)) + { + SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true); + SendParcelOverlay(client); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "LandManagementModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region Parcel Add/Remove/Get/Create + + public void SetAllowedForcefulBans(bool forceful) + { + AllowedForcefulBans = forceful; + } + + public void UpdateLandObject(int local_id, LandData data) + { + LandData newData = data.Copy(); + newData.LocalID = local_id; + + lock (m_landList) + { + if (m_landList.ContainsKey(local_id)) + { + m_landList[local_id].landData = newData; + m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]); + } + } + } + + public bool AllowedForcefulBans + { + get { return m_allowedForcefulBans; } + set { m_allowedForcefulBans = value; } + } + + /// + /// Resets the sim to the default land object (full sim piece of land owned by the default user) + /// + public void ResetSimLandObjects() + { + //Remove all the land objects in the sim and add a blank, full sim land object set to public + lock (m_landList) + { + m_landList.Clear(); + m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; + m_landIDList.Initialize(); + } + + ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); + + fullSimParcel.setLandBitmap(fullSimParcel.getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + fullSimParcel.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + fullSimParcel.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; + fullSimParcel.landData.ClaimDate = Util.UnixTimeSinceEpoch(); + AddLandObject(fullSimParcel); + } + + public List AllParcels() + { + lock (m_landList) + { + return new List(m_landList.Values); + } + } + + public List ParcelsNearPoint(Vector3 position) + { + List parcelsNear = new List(); + for (int x = -4; x <= 4; x += 4) + { + for (int y = -4; y <= 4; y += 4) + { + ILandObject check = GetLandObject(position.X + x, position.Y + y); + if (check != null) + { + if (!parcelsNear.Contains(check)) + { + parcelsNear.Add(check); + } + } + } + } + + return parcelsNear; + } + + public void SendYouAreBannedNotice(ScenePresence avatar) + { + if (AllowedForcefulBans) + { + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because you are banned. Please go away."); + + avatar.PhysicsActor.Position = + new PhysicsVector(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y, + avatar.lastKnownAllowedPosition.Z); + avatar.PhysicsActor.Velocity = new PhysicsVector(0, 0, 0); + } + else + { + avatar.ControllingClient.SendAlertMessage( + "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!"); + } + } + + public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, UUID regionID) + { + if (m_scene.RegionInfo.RegionID == regionID) + { + ILandObject parcelAvatarIsEntering; + lock (m_landList) + { + parcelAvatarIsEntering = m_landList[localLandID]; + } + + if (parcelAvatarIsEntering != null) + { + if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) + { + if (parcelAvatarIsEntering.isBannedFromLand(avatar.UUID)) + { + SendYouAreBannedNotice(avatar); + } + else if (parcelAvatarIsEntering.isRestrictedFromLand(avatar.UUID)) + { + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!)."); + } + else + { + avatar.sentMessageAboutRestrictedParcelFlyingDown = true; + } + } + else + { + avatar.sentMessageAboutRestrictedParcelFlyingDown = true; + } + } + } + } + + public void SendOutNearestBanLine(IClientAPI avatar) + { + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence presence in avatars) + { + if (presence.UUID == avatar.AgentId) + { + List checkLandParcels = ParcelsNearPoint(presence.AbsolutePosition); + foreach (ILandObject checkBan in checkLandParcels) + { + if (checkBan.isBannedFromLand(avatar.AgentId)) + { + checkBan.sendLandProperties((int)ParcelStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar); + return; //Only send one + } + if (checkBan.isRestrictedFromLand(avatar.AgentId)) + { + checkBan.sendLandProperties((int)ParcelStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar); + return; //Only send one + } + } + return; + } + } + } + + public void SendLandUpdate(ScenePresence avatar, bool force) + { + ILandObject over = GetLandObject((int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), + (int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); + + if (over != null) + { + if (force) + { + if (!avatar.IsChildAgent) + { + over.sendLandUpdateToClient(avatar.ControllingClient); + m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID, + m_scene.RegionInfo.RegionID); + } + } + + if (avatar.currentParcelUUID != over.landData.GlobalID) + { + if (!avatar.IsChildAgent) + { + over.sendLandUpdateToClient(avatar.ControllingClient); + avatar.currentParcelUUID = over.landData.GlobalID; + m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID, + m_scene.RegionInfo.RegionID); + } + } + } + } + + public void SendLandUpdate(ScenePresence avatar) + { + SendLandUpdate(avatar, false); + } + + public void handleSignificantClientMovement(IClientAPI remote_client) + { + ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId); + + if (clientAvatar != null) + { + SendLandUpdate(clientAvatar); + SendOutNearestBanLine(remote_client); + ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); + if (parcel != null) + { + if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && + clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) + { + handleAvatarChangingParcel(clientAvatar, parcel.landData.LocalID, m_scene.RegionInfo.RegionID); + //They are going below the safety line! + if (!parcel.isBannedFromLand(clientAvatar.UUID)) + { + clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false; + } + } + else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && + parcel.isBannedFromLand(clientAvatar.UUID)) + { + SendYouAreBannedNotice(clientAvatar); + } + } + } + } + + public void handleAnyClientMovement(ScenePresence avatar) + //Like handleSignificantClientMovement, but called with an AgentUpdate regardless of distance. + { + ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + if (over != null) + { + if (!over.isBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT) + { + avatar.lastKnownAllowedPosition = + new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); + } + } + } + + + public void handleParcelAccessRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID, + int landLocalID, IClientAPI remote_client) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(landLocalID, out land); + } + + if (land != null) + { + m_landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client); + } + } + + public void handleParcelAccessUpdateRequest(UUID agentID, UUID sessionID, uint flags, int landLocalID, + List entries, + IClientAPI remote_client) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(landLocalID, out land); + } + + if (land != null) + { + if (agentID == land.landData.OwnerID) + { + land.updateAccessList(flags, entries, remote_client); + } + } + else + { + m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID); + } + } + + /// + /// Creates a basic Parcel object without an owner (a zeroed key) + /// + /// + public ILandObject CreateBaseLand() + { + return new LandObject(UUID.Zero, false, m_scene); + } + + /// + /// Adds a land object to the stored list and adds them to the landIDList to what they own + /// + /// The land object being added + public ILandObject AddLandObject(ILandObject land) + { + ILandObject new_land = land.Copy(); + + lock (m_landList) + { + int newLandLocalID = ++m_lastLandLocalID; + new_land.landData.LocalID = newLandLocalID; + + bool[,] landBitmap = new_land.getLandBitmap(); + for (int x = 0; x < 64; x++) + { + for (int y = 0; y < 64; y++) + { + if (landBitmap[x, y]) + { + m_landIDList[x, y] = newLandLocalID; + } + } + } + + m_landList.Add(newLandLocalID, new_land); + } + + new_land.forceUpdateLandInfo(); + m_scene.EventManager.TriggerLandObjectAdded(new_land); + return new_land; + } + + /// + /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList + /// + /// Land.localID of the peice of land to remove. + public void removeLandObject(int local_id) + { + lock (m_landList) + { + for (int x = 0; x < 64; x++) + { + for (int y = 0; y < 64; y++) + { + if (m_landIDList[x, y] == local_id) + { + m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}", + local_id, x, y); + return; + //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); + } + } + } + + m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].landData.GlobalID); + m_landList.Remove(local_id); + } + } + + private void performFinalLandJoin(ILandObject master, ILandObject slave) + { + bool[,] landBitmapSlave = slave.getLandBitmap(); + lock (m_landList) + { + for (int x = 0; x < 64; x++) + { + for (int y = 0; y < 64; y++) + { + if (landBitmapSlave[x, y]) + { + m_landIDList[x, y] = master.landData.LocalID; + } + } + } + } + + removeLandObject(slave.landData.LocalID); + UpdateLandObject(master.landData.LocalID, master.landData); + } + + public ILandObject GetLandObject(int parcelLocalID) + { + lock (m_landList) + { + if (m_landList.ContainsKey(parcelLocalID)) + { + return m_landList[parcelLocalID]; + } + } + return null; + } + + /// + /// Get the land object at the specified point + /// + /// Value between 0 - 256 on the x axis of the point + /// Value between 0 - 256 on the y axis of the point + /// Land object at the point supplied + public ILandObject GetLandObject(float x_float, float y_float) + { + int x; + int y; + + try + { + x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0)); + y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0)); + } + catch (OverflowException) + { + return null; + } + + if (x >= 64 || y >= 64 || x < 0 || y < 0) + { + return null; + } + lock (m_landList) + { + // Corner case. If an autoreturn happens during sim startup + // we will come here with the list uninitialized + // + if (m_landList.ContainsKey(m_landIDList[x, y])) + return m_landList[m_landIDList[x, y]]; + return null; + } + } + + public ILandObject GetLandObject(int x, int y) + { + if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) + { + // These exceptions here will cause a lot of complaints from the users specifically because + // they happen every time at border crossings + throw new Exception("Error: Parcel not found at point " + x + ", " + y); + } + lock (m_landIDList) + { + return m_landList[m_landIDList[x / 4, y / 4]]; + } + } + + #endregion + + #region Parcel Modification + + public void ResetAllLandPrimCounts() + { + lock (m_landList) + { + foreach (LandObject p in m_landList.Values) + { + p.resetLandPrimCounts(); + } + } + } + + public void SetPrimsTainted() + { + m_landPrimCountTainted = true; + } + + public bool IsLandPrimCountTainted() + { + return m_landPrimCountTainted; + } + + public void AddPrimToLandPrimCounts(SceneObjectGroup obj) + { + Vector3 position = obj.AbsolutePosition; + ILandObject landUnderPrim = GetLandObject(position.X, position.Y); + if (landUnderPrim != null) + { + landUnderPrim.addPrimToCount(obj); + } + } + + public void RemovePrimFromLandPrimCounts(SceneObjectGroup obj) + { + + lock (m_landList) + { + foreach (LandObject p in m_landList.Values) + { + p.removePrimFromCount(obj); + } + } + } + + public void FinalizeLandPrimCountUpdate() + { + //Get Simwide prim count for owner + Dictionary> landOwnersAndParcels = new Dictionary>(); + lock (m_landList) + { + foreach (LandObject p in m_landList.Values) + { + if (!landOwnersAndParcels.ContainsKey(p.landData.OwnerID)) + { + List tempList = new List(); + tempList.Add(p); + landOwnersAndParcels.Add(p.landData.OwnerID, tempList); + } + else + { + landOwnersAndParcels[p.landData.OwnerID].Add(p); + } + } + } + + foreach (UUID owner in landOwnersAndParcels.Keys) + { + int simArea = 0; + int simPrims = 0; + foreach (LandObject p in landOwnersAndParcels[owner]) + { + simArea += p.landData.Area; + simPrims += p.landData.OwnerPrims + p.landData.OtherPrims + p.landData.GroupPrims + + p.landData.SelectedPrims; + } + + foreach (LandObject p in landOwnersAndParcels[owner]) + { + p.landData.SimwideArea = simArea; + p.landData.SimwidePrims = simPrims; + } + } + } + + public void UpdateLandPrimCounts() + { + ResetAllLandPrimCounts(); + foreach (EntityBase obj in m_scene.Entities) + { + if (obj != null) + { + if ((obj is SceneObjectGroup) && !obj.IsDeleted && !((SceneObjectGroup) obj).IsAttachment) + { + m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup) obj); + } + } + } + FinalizeLandPrimCountUpdate(); + m_landPrimCountTainted = false; + } + + public void PerformParcelPrimCountUpdate() + { + ResetAllLandPrimCounts(); + m_scene.EventManager.TriggerParcelPrimCountUpdate(); + FinalizeLandPrimCountUpdate(); + m_landPrimCountTainted = false; + } + + /// + /// Subdivides a piece of land + /// + /// West Point + /// South Point + /// East Point + /// North Point + /// UUID of user who is trying to subdivide + /// Returns true if successful + private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) + { + //First, lets loop through the points and make sure they are all in the same peice of land + //Get the land object at start + + ILandObject startLandObject = GetLandObject(start_x, start_y); + + if (startLandObject == null) return; + + //Loop through the points + try + { + int totalX = end_x - start_x; + int totalY = end_y - start_y; + for (int y = 0; y < totalY; y++) + { + for (int x = 0; x < totalX; x++) + { + ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y); + if (tempLandObject == null) return; + if (tempLandObject != startLandObject) return; + } + } + } + catch (Exception) + { + return; + } + + //If we are still here, then they are subdividing within one piece of land + //Check owner + if (!m_scene.Permissions.CanEditParcel(attempting_user_id, startLandObject)) + { + return; + } + + //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) + ILandObject newLand = startLandObject.Copy(); + newLand.landData.Name = "Subdivision of " + newLand.landData.Name; + newLand.landData.GlobalID = UUID.Random(); + + newLand.setLandBitmap(newLand.getSquareLandBitmap(start_x, start_y, end_x, end_y)); + + //Now, lets set the subdivision area of the original to false + int startLandObjectIndex = startLandObject.landData.LocalID; + lock (m_landList) + { + m_landList[startLandObjectIndex].setLandBitmap( + newLand.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false)); + m_landList[startLandObjectIndex].forceUpdateLandInfo(); + } + + SetPrimsTainted(); + + //Now add the new land object + ILandObject result = AddLandObject(newLand); + UpdateLandObject(startLandObject.landData.LocalID, startLandObject.landData); + result.sendLandUpdateToAvatarsOverMe(); + } + + /// + /// Join 2 land objects together + /// + /// x value in first piece of land + /// y value in first piece of land + /// x value in second peice of land + /// y value in second peice of land + /// UUID of the avatar trying to join the land objects + /// Returns true if successful + private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) + { + end_x -= 4; + end_y -= 4; + + List selectedLandObjects = new List(); + int stepYSelected; + for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4) + { + int stepXSelected; + for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4) + { + ILandObject p = GetLandObject(stepXSelected, stepYSelected); + + if (p != null) + { + if (!selectedLandObjects.Contains(p)) + { + selectedLandObjects.Add(p); + } + } + } + } + ILandObject masterLandObject = selectedLandObjects[0]; + selectedLandObjects.RemoveAt(0); + + if (selectedLandObjects.Count < 1) + { + return; + } + if (!m_scene.Permissions.CanEditParcel(attempting_user_id, masterLandObject)) + { + return; + } + foreach (ILandObject p in selectedLandObjects) + { + if (p.landData.OwnerID != masterLandObject.landData.OwnerID) + { + return; + } + } + + lock (m_landList) + { + foreach (ILandObject slaveLandObject in selectedLandObjects) + { + m_landList[masterLandObject.landData.LocalID].setLandBitmap( + slaveLandObject.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap())); + performFinalLandJoin(masterLandObject, slaveLandObject); + } + } + SetPrimsTainted(); + + masterLandObject.sendLandUpdateToAvatarsOverMe(); + } + + #endregion + + #region Parcel Updating + + /// + /// Where we send the ParcelOverlay packet to the client + /// + /// The object representing the client + public void SendParcelOverlay(IClientAPI remote_client) + { + const int LAND_BLOCKS_PER_PACKET = 1024; + + byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; + int byteArrayCount = 0; + int sequenceID = 0; + + for (int y = 0; y < 64; y++) + { + for (int x = 0; x < 64; x++) + { + byte tempByte = 0; //This represents the byte for the current 4x4 + + ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); + + if (currentParcelBlock != null) + { + if (currentParcelBlock.landData.OwnerID == remote_client.AgentId) + { + //Owner Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); + } + else if (currentParcelBlock.landData.SalePrice > 0 && + (currentParcelBlock.landData.AuthBuyerID == UUID.Zero || + currentParcelBlock.landData.AuthBuyerID == remote_client.AgentId)) + { + //Sale Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE); + } + else if (currentParcelBlock.landData.OwnerID == UUID.Zero) + { + //Public Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC); + } + else + { + //Other Flag + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER); + } + + //Now for border control + + ILandObject westParcel = null; + ILandObject southParcel = null; + if (x > 0) + { + westParcel = GetLandObject((x - 1) * 4, y * 4); + } + if (y > 0) + { + southParcel = GetLandObject(x * 4, (y - 1) * 4); + } + + if (x == 0) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); + } + else if (westParcel != null && westParcel != currentParcelBlock) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); + } + + if (y == 0) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); + } + else if (southParcel != null && southParcel != currentParcelBlock) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); + } + + byteArray[byteArrayCount] = tempByte; + byteArrayCount++; + if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) + { + remote_client.SendLandParcelOverlay(byteArray, sequenceID); + byteArrayCount = 0; + sequenceID++; + byteArray = new byte[LAND_BLOCKS_PER_PACKET]; + } + } + } + } + } + + public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, + bool snap_selection, IClientAPI remote_client) + { + //Get the land objects within the bounds + List temp = new List(); + int inc_x = end_x - start_x; + int inc_y = end_y - start_y; + for (int x = 0; x < inc_x; x++) + { + for (int y = 0; y < inc_y; y++) + { + ILandObject currentParcel = GetLandObject(start_x + x, start_y + y); + + if (currentParcel != null) + { + if (!temp.Contains(currentParcel)) + { + currentParcel.forceUpdateLandInfo(); + temp.Add(currentParcel); + } + } + } + } + + int requestResult = LandChannel.LAND_RESULT_SINGLE; + if (temp.Count > 1) + { + requestResult = LandChannel.LAND_RESULT_MULTIPLE; + } + + for (int i = 0; i < temp.Count; i++) + { + temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client); + } + + SendParcelOverlay(remote_client); + } + + public void handleParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(localID, out land); + } + + if (land != null) land.updateLandProperties(args, remote_client); + } + + public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) + { + subdivide(west, south, east, north, remote_client.AgentId); + } + + public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) + { + join(west, south, east, north, remote_client.AgentId); + } + + public void handleParcelSelectObjectsRequest(int local_id, int request_type, List returnIDs, IClientAPI remote_client) + { + m_landList[local_id].sendForceObjectSelect(local_id, request_type, returnIDs, remote_client); + } + + public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(local_id, out land); + } + + if (land != null) + { + m_landList[local_id].sendLandObjectOwners(remote_client); + } + else + { + m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id); + } + } + + public void handleParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(local_id, out land); + } + + if (land != null) + { + if (m_scene.Permissions.IsGod(remote_client.AgentId)) + { + land.landData.OwnerID = ownerID; + + m_scene.Broadcast(SendParcelOverlay); + land.sendLandUpdateToClient(remote_client); + } + } + } + + public void handleParcelAbandonRequest(int local_id, IClientAPI remote_client) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(local_id, out land); + } + + if (land != null) + { + if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land)) + { + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; + m_scene.Broadcast(SendParcelOverlay); + land.sendLandUpdateToClient(remote_client); + } + } + } + + public void handleParcelReclaim(int local_id, IClientAPI remote_client) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(local_id, out land); + } + + if (land != null) + { + if (m_scene.Permissions.CanReclaimParcel(remote_client.AgentId, land)) + { + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + else + land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; + land.landData.ClaimDate = Util.UnixTimeSinceEpoch(); + m_scene.Broadcast(SendParcelOverlay); + land.sendLandUpdateToClient(remote_client); + } + } + } + #endregion + + // If the economy has been validated by the economy module, + // and land has been validated as well, this method transfers + // the land ownership + + public void handleLandBuyRequest(Object o, EventManager.LandBuyArgs e) + { + if (e.economyValidated && e.landValidated) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(e.parcelLocalID, out land); + } + + if (land != null) + { + land.updateLandSold(e.agentId, e.groupId, e.groupOwned, (uint)e.transactionID, e.parcelPrice, e.parcelArea); + } + } + } + + // After receiving a land buy packet, first the data needs to + // be validated. This method validates the right to buy the + // parcel + + public void handleLandValidationRequest(Object o, EventManager.LandBuyArgs e) + { + if (e.landValidated == false) + { + ILandObject lob = null; + lock (m_landList) + { + m_landList.TryGetValue(e.parcelLocalID, out lob); + } + + if (lob != null) + { + UUID AuthorizedID = lob.landData.AuthBuyerID; + int saleprice = lob.landData.SalePrice; + UUID pOwnerID = lob.landData.OwnerID; + + bool landforsale = ((lob.landData.Flags & + (uint)(Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects)) != 0); + if ((AuthorizedID == UUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale) + { + // TODO I don't think we have to lock it here, no? + //lock (e) + //{ + e.parcelOwnerID = pOwnerID; + e.landValidated = true; + //} + } + } + } + } + + #region Land Object From Storage Functions + + public void IncomingLandObjectsFromStorage(List data) + { + for (int i = 0; i < data.Count; i++) + { + IncomingLandObjectFromStorage(data[i]); + } + } + + public void IncomingLandObjectFromStorage(LandData data) + { + ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); + new_land.landData = data.Copy(); + new_land.setLandBitmapFromByteArray(); + AddLandObject(new_land); + } + + public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) + { + ILandObject selectedParcel = null; + lock (m_landList) + { + m_landList.TryGetValue(localID, out selectedParcel); + } + + if (selectedParcel == null) return; + + selectedParcel.returnLandObjects(returnType, agentIDs, taskIDs, remoteClient); + } + + public void NoLandDataFromStorage() + { + ResetSimLandObjects(); + } + + #endregion + + public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) + { + lock (m_landList) + { + foreach (LandObject obj in m_landList.Values) + { + obj.setParcelObjectMaxOverride(overrideDel); + } + } + } + + public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) + { + } + + #region CAPS handler + + private void OnRegisterCaps(UUID agentID, Caps caps) + { + string capsBase = "/CAPS/" + caps.CapsObjectPath; + caps.RegisterHandler("RemoteParcelRequest", + new RestStreamHandler("POST", capsBase + remoteParcelRequestPath, + delegate(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return RemoteParcelRequest(request, path, param, agentID, caps); + })); + } + + // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the + // "real" parcelID, because we wouldn't be able to map that to the region the parcel belongs to. + // So, we create a "fake" parcelID by using the regionHandle (64 bit), and the local (integer) x + // and y coordinate (each 8 bit), encoded in a UUID (128 bit). + // + // Request format: + // + // + // location + // + // 1.23 + // 45..6 + // 78.9 + // + // region_id + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + // + // + private string RemoteParcelRequest(string request, string path, string param, UUID agentID, Caps caps) + { + UUID parcelID = UUID.Zero; + try + { + Hashtable hash = new Hashtable(); + hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); + if (hash.ContainsKey("region_id") && hash.ContainsKey("location")) + { + UUID regionID = (UUID)hash["region_id"]; + ArrayList list = (ArrayList)hash["location"]; + uint x = (uint)(double)list[0]; + uint y = (uint)(double)list[1]; + if (hash.ContainsKey("region_handle")) + { + // if you do a "About Landmark" on a landmark a second time, the viewer sends the + // region_handle it got earlier via RegionHandleRequest + ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]); + parcelID = Util.BuildFakeParcelID(regionHandle, x, y); + } + else if (regionID == m_scene.RegionInfo.RegionID) + { + // a parcel request for a local parcel => no need to query the grid + parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y); + } + else + { + // a parcel request for a parcel in another region. Ask the grid about the region + RegionInfo info = m_scene.CommsManager.GridService.RequestNeighbourInfo(regionID); + if (info != null) + parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y); + } + } + } + catch (LLSD.LLSDParseException e) + { + m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message); + m_log.ErrorFormat("[LAND] ... in request {0}", request); + } + catch(InvalidCastException) + { + m_log.ErrorFormat("[LAND] Wrong type in request {0}", request); + } + + LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); + response.parcel_id = parcelID; + m_log.DebugFormat("[LAND] got parcelID {0}", parcelID); + + return LLSDHelpers.SerialiseLLSDReply(response); + } + + #endregion + + private void handleParcelDwell(int localID, IClientAPI remoteClient) + { + ILandObject selectedParcel = null; + lock (m_landList) + { + if (!m_landList.TryGetValue(localID, out selectedParcel)) + return; + } + + remoteClient.SendParcelDwellReply(localID, selectedParcel.landData.GlobalID, selectedParcel.landData.Dwell); + } + + private void handleParcelInfo(IClientAPI remoteClient, UUID parcelID) + { + if (parcelID == UUID.Zero) + return; + + ExtendedLandData data = (ExtendedLandData)parcelInfoCache.Get(parcelID, delegate(UUID parcel) { + // assume we've got the parcelID we just computed in RemoteParcelRequest + ExtendedLandData extLandData = new ExtendedLandData(); + Util.ParseFakeParcelID(parcel, out extLandData.regionHandle, out extLandData.x, out extLandData.y); + m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}", + extLandData.regionHandle, extLandData.x, extLandData.y); + + // for this region or for somewhere else? + if (extLandData.regionHandle == m_scene.RegionInfo.RegionHandle) + { + extLandData.landData = this.GetLandObject(extLandData.x, extLandData.y).landData; + } + else + { + extLandData.landData = m_scene.CommsManager.GridService.RequestLandData(extLandData.regionHandle, + extLandData.x, + extLandData.y); + if (extLandData.landData == null) + { + // we didn't find the region/land => don't cache + return null; + } + } + return extLandData; + }); + + if (data != null) // if we found some data, send it + { + RegionInfo info; + if (data.regionHandle == m_scene.RegionInfo.RegionHandle) + { + info = m_scene.RegionInfo; + } + else + { + // most likely still cached from building the extLandData entry + info = m_scene.CommsManager.GridService.RequestNeighbourInfo(data.regionHandle); + } + // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. + m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...", + data.landData.Name, data.regionHandle); + remoteClient.SendParcelInfo(info, data.landData, parcelID, data.x, data.y); + } + else + m_log.Debug("[LAND] got no parcelinfo; not sending"); + } + + public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(localID, out land); + } + + if (land == null) return; + + if (!m_scene.Permissions.CanEditParcel(remoteClient.AgentId, land)) + return; + + land.landData.OtherCleanTime = otherCleanTime; + + UpdateLandObject(localID, land.landData); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs new file mode 100644 index 0000000..fc5bef1 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -0,0 +1,930 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Land +{ + /// + /// Keeps track of a specific piece of land's information + /// + public class LandObject : ILandObject + { + #region Member Variables + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private bool[,] m_landBitmap = new bool[64,64]; + + protected LandData m_landData = new LandData(); + protected Scene m_scene; + protected List primsOverMe = new List(); + + public bool[,] landBitmap + { + get { return m_landBitmap; } + set { m_landBitmap = value; } + } + + #endregion + + #region ILandObject Members + + public LandData landData + { + get { return m_landData; } + + set { m_landData = value; } + } + + public UUID regionUUID + { + get { return m_scene.RegionInfo.RegionID; } + } + + #region Constructors + + public LandObject(UUID owner_id, bool is_group_owned, Scene scene) + { + m_scene = scene; + landData.OwnerID = owner_id; + landData.IsGroupOwned = is_group_owned; + } + + #endregion + + #region Member Functions + + #region General Functions + + /// + /// Checks to see if this land object contains a point + /// + /// + /// + /// Returns true if the piece of land contains the specified point + public bool containsPoint(int x, int y) + { + if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize) + { + return (landBitmap[x / 4, y / 4] == true); + } + else + { + return false; + } + } + + public ILandObject Copy() + { + ILandObject newLand = new LandObject(landData.OwnerID, landData.IsGroupOwned, m_scene); + + //Place all new variables here! + newLand.landBitmap = (bool[,]) (landBitmap.Clone()); + newLand.landData = landData.Copy(); + + return newLand; + } + + + static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount; + static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount; + + public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) + { + overrideParcelMaxPrimCount = overrideDel; + } + public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) + { + overrideSimulatorMaxPrimCount = overrideDel; + } + + public int getParcelMaxPrimCount(ILandObject thisObject) + { + if (overrideParcelMaxPrimCount != null) + { + return overrideParcelMaxPrimCount(thisObject); + } + else + { + //Normal Calculations + return Convert.ToInt32( + Math.Round((Convert.ToDecimal(landData.Area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity * + Convert.ToDecimal(m_scene.RegionInfo.RegionSettings.ObjectBonus))); ; + } + } + public int getSimulatorMaxPrimCount(ILandObject thisObject) + { + if (overrideSimulatorMaxPrimCount != null) + { + return overrideSimulatorMaxPrimCount(thisObject); + } + else + { + //Normal Calculations + return m_scene.objectCapacity; + } + } + #endregion + + #region Packet Request Handling + + public void sendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) + { + IEstateModule estateModule = m_scene.RequestModuleInterface(); + uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); + if (estateModule != null) + regionFlags = estateModule.GetRegionFlags(); + + // In a perfect world, this would have worked. + // +// if ((landData.Flags & (uint)Parcel.ParcelFlags.AllowLandmark) != 0) +// regionFlags |= (uint)RegionFlags.AllowLandmark; +// if (landData.OwnerID == remote_client.AgentId) +// regionFlags |= (uint)RegionFlags.AllowSetHome; + remote_client.SendLandProperties(sequence_id, + snap_selection, request_result, landData, + (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, + getParcelMaxPrimCount(this), + getSimulatorMaxPrimCount(this), regionFlags); + } + + public void updateLandProperties(LandUpdateArgs args, IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this)) + { + //Needs later group support + LandData newData = landData.Copy(); + + if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice) + { + if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this)) + { + newData.AuthBuyerID = args.AuthBuyerID; + newData.SalePrice = args.SalePrice; + } + } + newData.Category = args.Category; + newData.Description = args.Desc; + newData.GroupID = args.GroupID; + newData.LandingType = args.LandingType; + newData.MediaAutoScale = args.MediaAutoScale; + newData.MediaID = args.MediaID; + newData.MediaURL = args.MediaURL; + newData.MusicURL = args.MusicURL; + newData.Name = args.Name; + newData.Flags = args.ParcelFlags; + newData.PassHours = args.PassHours; + newData.PassPrice = args.PassPrice; + newData.SnapshotID = args.SnapshotID; + newData.UserLocation = args.UserLocation; + newData.UserLookAt = args.UserLookAt; + + m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData); + + sendLandUpdateToAvatarsOverMe(); + } + } + + public void updateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) + { + LandData newData = landData.Copy(); + newData.OwnerID = avatarID; + newData.GroupID = groupID; + newData.IsGroupOwned = groupOwned; + //newData.auctionID = AuctionID; + newData.ClaimDate = Util.UnixTimeSinceEpoch(); + newData.ClaimPrice = claimprice; + newData.SalePrice = 0; + newData.AuthBuyerID = UUID.Zero; + newData.Flags &= ~(uint) (Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects); + m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData); + + sendLandUpdateToAvatarsOverMe(); + } + + public bool isEitherBannedOrRestricted(UUID avatar) + { + if (isBannedFromLand(avatar)) + { + return true; + } + else if (isRestrictedFromLand(avatar)) + { + return true; + } + return false; + } + + public bool isBannedFromLand(UUID avatar) + { + if ((landData.Flags & (uint) Parcel.ParcelFlags.UseBanList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + if (landData.ParcelAccessList.Contains(entry)) + { + //They are banned, so lets send them a notice about this parcel + return true; + } + } + return false; + } + + public bool isRestrictedFromLand(UUID avatar) + { + if ((landData.Flags & (uint) Parcel.ParcelFlags.UseAccessList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = AccessList.Access; + entry.Time = new DateTime(); + if (!landData.ParcelAccessList.Contains(entry)) + { + //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel + return true; + } + } + return false; + } + + public void sendLandUpdateToClient(IClientAPI remote_client) + { + sendLandProperties(0, false, 0, remote_client); + } + + public void sendLandUpdateToAvatarsOverMe() + { + List avatars = m_scene.GetAvatars(); + ILandObject over = null; + for (int i = 0; i < avatars.Count; i++) + { + try + { + over = + m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatars[i].AbsolutePosition.X), 0, 255), + Util.Clamp((int)Math.Round(avatars[i].AbsolutePosition.Y), 0, 255)); + } + catch (Exception) + { + m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatars[i].AbsolutePosition.X) + " y: " + + Math.Round(avatars[i].AbsolutePosition.Y)); + } + + if (over != null) + { + if (over.landData.LocalID == landData.LocalID) + { + if (((over.landData.Flags & (uint)Parcel.ParcelFlags.AllowDamage) != 0) && m_scene.RegionInfo.RegionSettings.AllowDamage) + avatars[i].Invulnerable = false; + else + avatars[i].Invulnerable = true; + + sendLandUpdateToClient(avatars[i].ControllingClient); + } + } + } + } + + #endregion + + #region AccessList Functions + + public List createAccessListArrayByFlag(AccessList flag) + { + List list = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in landData.ParcelAccessList) + { + if (entry.Flags == flag) + { + list.Add(entry.AgentID); + } + } + if (list.Count == 0) + { + list.Add(UUID.Zero); + } + + return list; + } + + public void sendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, + IClientAPI remote_client) + { + + if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) + { + List avatars = createAccessListArrayByFlag(AccessList.Access); + remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,landData.LocalID); + } + + if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) + { + List avatars = createAccessListArrayByFlag(AccessList.Ban); + remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, landData.LocalID); + } + } + + public void updateAccessList(uint flags, List entries, IClientAPI remote_client) + { + LandData newData = landData.Copy(); + + if (entries.Count == 1 && entries[0].AgentID == UUID.Zero) + { + entries.Clear(); + } + + List toRemove = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList) + { + if (entry.Flags == (AccessList)flags) + { + toRemove.Add(entry); + } + } + + foreach (ParcelManager.ParcelAccessEntry entry in toRemove) + { + newData.ParcelAccessList.Remove(entry); + } + foreach (ParcelManager.ParcelAccessEntry entry in entries) + { + ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); + temp.AgentID = entry.AgentID; + temp.Time = new DateTime(); //Pointless? Yes. + temp.Flags = (AccessList)flags; + + if (!newData.ParcelAccessList.Contains(temp)) + { + newData.ParcelAccessList.Add(temp); + } + } + + m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData); + } + + #endregion + + #region Update Functions + + public void updateLandBitmapByteArray() + { + landData.Bitmap = convertLandBitmapToBytes(); + } + + /// + /// Update all settings in land such as area, bitmap byte array, etc + /// + public void forceUpdateLandInfo() + { + updateAABBAndAreaValues(); + updateLandBitmapByteArray(); + } + + public void setLandBitmapFromByteArray() + { + landBitmap = convertBytesToLandBitmap(); + } + + /// + /// Updates the AABBMin and AABBMax values after area/shape modification of the land object + /// + private void updateAABBAndAreaValues() + { + int min_x = 64; + int min_y = 64; + int max_x = 0; + int max_y = 0; + int tempArea = 0; + int x, y; + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (landBitmap[x, y] == true) + { + if (min_x > x) min_x = x; + if (min_y > y) min_y = y; + if (max_x < x) max_x = x; + if (max_y < y) max_y = y; + tempArea += 16; //16sqm peice of land + } + } + } + int tx = min_x * 4; + if (tx > 255) + tx = 255; + int ty = min_y * 4; + if (ty > 255) + ty = 255; + landData.AABBMin = + new Vector3((float) (min_x * 4), (float) (min_y * 4), + (float) m_scene.Heightmap[tx, ty]); + + tx = max_x * 4; + if (tx > 255) + tx = 255; + ty = max_y * 4; + if (ty > 255) + ty = 255; + landData.AABBMax = + new Vector3((float) (max_x * 4), (float) (max_y * 4), + (float) m_scene.Heightmap[tx, ty]); + landData.Area = tempArea; + } + + #endregion + + #region Land Bitmap Functions + + /// + /// Sets the land's bitmap manually + /// + /// 64x64 block representing where this land is on a map + public void setLandBitmap(bool[,] bitmap) + { + if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap"); + } + else + { + //Valid: Lets set it + landBitmap = bitmap; + forceUpdateLandInfo(); + } + } + + /// + /// Gets the land's bitmap manually + /// + /// + public bool[,] getLandBitmap() + { + return landBitmap; + } + + /// + /// Full sim land object creation + /// + /// + public bool[,] basicFullRegionLandBitmap() + { + return getSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); + } + + /// + /// Used to modify the bitmap between the x and y points. Points use 64 scale + /// + /// + /// + /// + /// + /// + public bool[,] getSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) + { + bool[,] tempBitmap = new bool[64,64]; + tempBitmap.Initialize(); + + tempBitmap = modifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); + return tempBitmap; + } + + /// + /// Change a land bitmap at within a square and set those points to a specific value + /// + /// + /// + /// + /// + /// + /// + /// + public bool[,] modifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, + bool set_value) + { + if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (x >= start_x / 4 && x < end_x / 4 + && y >= start_y / 4 && y < end_y / 4) + { + land_bitmap[x, y] = set_value; + } + } + } + return land_bitmap; + } + + /// + /// Join the true values of 2 bitmaps together + /// + /// + /// + /// + public bool[,] mergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) + { + if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); + } + if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (bitmap_add[x, y]) + { + bitmap_base[x, y] = true; + } + } + } + return bitmap_base; + } + + /// + /// Converts the land bitmap to a packet friendly byte array + /// + /// + private byte[] convertLandBitmapToBytes() + { + byte[] tempConvertArr = new byte[512]; + byte tempByte = 0; + int x, y, i, byteNum = 0; + i = 0; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + tempByte = Convert.ToByte(tempByte | Convert.ToByte(landBitmap[x, y]) << (i++ % 8)); + if (i % 8 == 0) + { + tempConvertArr[byteNum] = tempByte; + tempByte = (byte) 0; + i = 0; + byteNum++; + } + } + } + return tempConvertArr; + } + + private bool[,] convertBytesToLandBitmap() + { + bool[,] tempConvertMap = new bool[64,64]; + tempConvertMap.Initialize(); + byte tempByte = 0; + int x = 0, y = 0, i = 0, bitNum = 0; + for (i = 0; i < 512; i++) + { + tempByte = landData.Bitmap[i]; + for (bitNum = 0; bitNum < 8; bitNum++) + { + bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); + tempConvertMap[x, y] = bit; + x++; + if (x > 63) + { + x = 0; + y++; + } + } + } + return tempConvertMap; + } + + #endregion + + #region Object Select and Object Owner Listing + + public void sendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) + { + List resultLocalIDs = new List(); + try + { + lock (primsOverMe) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.LocalId > 0) + { + if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == landData.OwnerID) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == landData.GroupID && landData.GroupID != UUID.Zero) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER && + obj.OwnerID != remote_client.AgentId) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID)) + { + resultLocalIDs.Add(obj.LocalId); + } + } + } + } + } catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to force select the parcel objects. Arr."); + } + + remote_client.SendForceClientSelectObjects(resultLocalIDs); + } + } + + /// + /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes + /// aggreagete details such as the number of prims. + /// + /// + /// + /// A + /// + public void sendLandObjectOwners(IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) + { + Dictionary primCount = new Dictionary(); + + lock (primsOverMe) + { + try + { + + foreach (SceneObjectGroup obj in primsOverMe) + { + try + { + if (!primCount.ContainsKey(obj.OwnerID)) + { + primCount.Add(obj.OwnerID, 0); + } + } + catch (NullReferenceException) + { + m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel"); + } + try + { + primCount[obj.OwnerID] += obj.PrimCount; + } + catch (KeyNotFoundException) + { + m_log.Error("[LAND]: Unable to match a prim with it's owner."); + } + } + } + catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to Enumerate Land object arr."); + } + } + + remote_client.SendLandObjectOwners(primCount); + } + } + + public Dictionary getLandObjectOwners() + { + Dictionary ownersAndCount = new Dictionary(); + lock (primsOverMe) + { + try + { + + foreach (SceneObjectGroup obj in primsOverMe) + { + if (!ownersAndCount.ContainsKey(obj.OwnerID)) + { + ownersAndCount.Add(obj.OwnerID, 0); + } + ownersAndCount[obj.OwnerID] += obj.PrimCount; + } + } + catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to enumerate land owners. arr."); + } + + } + return ownersAndCount; + } + + #endregion + + #region Object Returning + + public void returnObject(SceneObjectGroup obj) + { + SceneObjectGroup[] objs = new SceneObjectGroup[1]; + objs[0] = obj; + m_scene.returnObjects(objs, obj.OwnerID); + } + + public void returnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) + { + Dictionary> returns = + new Dictionary>(); + + lock (primsOverMe) + { + if (type == (uint)ObjectReturnType.Owner) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.OwnerID == m_landData.OwnerID) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.GroupID == m_landData.GroupID) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.Other) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.OwnerID != m_landData.OwnerID && + (obj.GroupID != m_landData.GroupID || + m_landData.GroupID == UUID.Zero)) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.List) + { + List ownerlist = new List(owners); + + foreach (SceneObjectGroup obj in primsOverMe) + { + if (ownerlist.Contains(obj.OwnerID)) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + } + + foreach (List ol in returns.Values) + m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); + } + + #endregion + + #region Object Adding/Removing from Parcel + + public void resetLandPrimCounts() + { + landData.GroupPrims = 0; + landData.OwnerPrims = 0; + landData.OtherPrims = 0; + landData.SelectedPrims = 0; + + + lock (primsOverMe) + primsOverMe.Clear(); + } + + public void addPrimToCount(SceneObjectGroup obj) + { + + UUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (obj.IsSelected) + { + landData.SelectedPrims += prim_count; + } + else + { + if (prim_owner == landData.OwnerID) + { + landData.OwnerPrims += prim_count; + } + else if ((obj.GroupID == landData.GroupID || + prim_owner == landData.GroupID) && + landData.GroupID != UUID.Zero) + { + landData.GroupPrims += prim_count; + } + else + { + landData.OtherPrims += prim_count; + } + } + + lock (primsOverMe) + primsOverMe.Add(obj); + } + + public void removePrimFromCount(SceneObjectGroup obj) + { + lock (primsOverMe) + { + if (primsOverMe.Contains(obj)) + { + UUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (prim_owner == landData.OwnerID) + { + landData.OwnerPrims -= prim_count; + } + else if (obj.GroupID == landData.GroupID || + prim_owner == landData.GroupID) + { + landData.GroupPrims -= prim_count; + } + else + { + landData.OtherPrims -= prim_count; + } + + primsOverMe.Remove(obj); + } + } + } + + #endregion + + #endregion + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs new file mode 100644 index 0000000..1469f5d --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -0,0 +1,1498 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; +using Nini.Config; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.Framework; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.CoreModules.World.Permissions +{ + public class PermissionsModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + #region Constants + // These are here for testing. They will be taken out + + //private uint PERM_ALL = (uint)2147483647; + private uint PERM_COPY = (uint)32768; + //private uint PERM_MODIFY = (uint)16384; + private uint PERM_MOVE = (uint)524288; + //private uint PERM_TRANS = (uint)8192; + private uint PERM_LOCKED = (uint)540672; + + /// + /// Different user set names that come in from the configuration file. + /// + enum UserSet + { + All, + Administrators + }; + + #endregion + + #region Bypass Permissions / Debug Permissions Stuff + + // Bypasses the permissions engine + private bool m_bypassPermissions = true; + private bool m_bypassPermissionsValue = true; + private bool m_propagatePermissions = false; + private bool m_debugPermissions = false; + private bool m_allowGridGods = false; + private bool m_RegionOwnerIsGod = false; + private bool m_ParcelOwnerIsGod = false; + + /// + /// The set of users that are allowed to create scripts. This is only active if permissions are not being + /// bypassed. This overrides normal permissions. + /// + private UserSet m_allowedScriptCreators = UserSet.All; + + /// + /// The set of users that are allowed to edit (save) scripts. This is only active if + /// permissions are not being bypassed. This overrides normal permissions.- + /// + private UserSet m_allowedScriptEditors = UserSet.All; + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + + IConfig myConfig = config.Configs["Startup"]; + + string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); + + List modules=new List(permissionModules.Split(',')); + + if (!modules.Contains("DefaultPermissionsModule")) + return; + + m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false); + m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true); + m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true); + m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true); + m_ParcelOwnerIsGod = myConfig.GetBoolean("parcel_owner_is_god", true); + + m_allowedScriptCreators + = ParseUserSetConfigSetting(myConfig, "allowed_script_creators", m_allowedScriptCreators); + m_allowedScriptEditors + = ParseUserSetConfigSetting(myConfig, "allowed_script_editors", m_allowedScriptEditors); + + if (m_bypassPermissions) + m_log.Info("[PERMISSIONS]: serviceside_object_permissions = false in ini file so disabling all region service permission checks"); + else + m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); + + //Register functions with Scene External Checks! + m_scene.Permissions.AddBypassPermissionsHandler(BypassPermissions); //FULLY IMPLEMENTED + m_scene.Permissions.AddSetBypassPermissionsHandler(SetBypassPermissions); //FULLY IMPLEMENTED + m_scene.Permissions.AddPropagatePermissionsHandler(PropagatePermissions); //FULLY IMPLEMENTED + m_scene.Permissions.AddGenerateClientFlagsHandler(GenerateClientFlags); //NOT YET FULLY IMPLEMENTED + m_scene.Permissions.AddAbandonParcelHandler(CanAbandonParcel); //FULLY IMPLEMENTED + m_scene.Permissions.AddReclaimParcelHandler(CanReclaimParcel); //FULLY IMPLEMENTED + m_scene.Permissions.AddIsGodHandler(IsGod); //FULLY IMPLEMENTED + m_scene.Permissions.AddDuplicateObjectHandler(CanDuplicateObject); //FULLY IMPLEMENTED + m_scene.Permissions.AddDeleteObjectHandler(CanDeleteObject); //MAYBE FULLY IMPLEMENTED + m_scene.Permissions.AddEditObjectHandler(CanEditObject);//MAYBE FULLY IMPLEMENTED + m_scene.Permissions.AddEditParcelHandler(CanEditParcel); //FULLY IMPLEMENTED + m_scene.Permissions.AddInstantMessageHandler(CanInstantMessage); //FULLY IMPLEMENTED + m_scene.Permissions.AddInventoryTransferHandler(CanInventoryTransfer); //NOT YET IMPLEMENTED + m_scene.Permissions.AddIssueEstateCommandHandler(CanIssueEstateCommand); //FULLY IMPLEMENTED + m_scene.Permissions.AddMoveObjectHandler(CanMoveObject); //HOPEFULLY FULLY IMPLEMENTED + m_scene.Permissions.AddObjectEntryHandler(CanObjectEntry); //FULLY IMPLEMENTED + m_scene.Permissions.AddReturnObjectHandler(CanReturnObject); //NOT YET IMPLEMENTED + m_scene.Permissions.AddRezObjectHandler(CanRezObject); //HOPEFULLY FULLY IMPLEMENTED + m_scene.Permissions.AddRunConsoleCommandHandler(CanRunConsoleCommand); //FULLY IMPLEMENTED + m_scene.Permissions.AddRunScriptHandler(CanRunScript); //NOT YET IMPLEMENTED + m_scene.Permissions.AddSellParcelHandler(CanSellParcel); //FULLY IMPLEMENTED + m_scene.Permissions.AddTakeObjectHandler(CanTakeObject); //FULLY IMPLEMENTED + m_scene.Permissions.AddTakeCopyObjectHandler(CanTakeCopyObject); //FULLY IMPLEMENTED + m_scene.Permissions.AddTerraformLandHandler(CanTerraformLand); //FULL IMPLEMENTED (POINT ONLY!!! NOT AREA!!!) + m_scene.Permissions.AddCanLinkObjectHandler(CanLinkObject); //NOT YET IMPLEMENTED + m_scene.Permissions.AddCanDelinkObjectHandler(CanDelinkObject); //NOT YET IMPLEMENTED + m_scene.Permissions.AddCanBuyLandHandler(CanBuyLand); //NOT YET IMPLEMENTED + + m_scene.Permissions.AddViewNotecardHandler(CanViewNotecard); //NOT YET IMPLEMENTED + m_scene.Permissions.AddViewScriptHandler(CanViewScript); //NOT YET IMPLEMENTED + m_scene.Permissions.AddEditNotecardHandler(CanEditNotecard); //NOT YET IMPLEMENTED + m_scene.Permissions.AddEditScriptHandler(CanEditScript); //NOT YET IMPLEMENTED + + m_scene.Permissions.AddCanCreateObjectInventoryHandler(CanCreateObjectInventory); //NOT IMPLEMENTED HERE + m_scene.Permissions.AddEditObjectInventoryHandler(CanEditObjectInventory);//MAYBE FULLY IMPLEMENTED + m_scene.Permissions.AddCanCopyObjectInventoryHandler(CanCopyObjectInventory); //NOT YET IMPLEMENTED + m_scene.Permissions.AddCanDeleteObjectInventoryHandler(CanDeleteObjectInventory); //NOT YET IMPLEMENTED + m_scene.Permissions.AddResetScriptHandler(CanResetScript); + + m_scene.Permissions.AddCanCreateUserInventoryHandler(CanCreateUserInventory); //NOT YET IMPLEMENTED + m_scene.Permissions.AddCanCopyUserInventoryHandler(CanCopyUserInventory); //NOT YET IMPLEMENTED + m_scene.Permissions.AddCanEditUserInventoryHandler(CanEditUserInventory); //NOT YET IMPLEMENTED + m_scene.Permissions.AddCanDeleteUserInventoryHandler(CanDeleteUserInventory); //NOT YET IMPLEMENTED + + m_scene.Permissions.AddCanTeleportHandler(CanTeleport); //NOT YET IMPLEMENTED + + m_scene.AddCommand("permissions", "bypass permissions", + "bypass permissions ", + "Bypass permission checks", + HandleBypassPermissions); + + m_scene.AddCommand("permissions", "force permissions", + "force permissions ", + "Force permissions on or off", + HandleForcePermissions); + + m_scene.AddCommand("permissions", "debug permissions", + "debug permissions ", + "Enable permissions debugging", + HandleDebugPermissions); + } + + public void HandleBypassPermissions(string module, string[] args) + { + if (m_scene.ConsoleScene() != null && + m_scene.ConsoleScene() != m_scene) + { + return; + } + + if (args.Length > 2) + { + bool val; + + if (!bool.TryParse(args[2], out val)) + return; + + m_bypassPermissions = val; + + m_log.InfoFormat( + "[PERMISSIONS]: Set permissions bypass to {0} for {1}", + m_bypassPermissions, m_scene.RegionInfo.RegionName); + } + } + + public void HandleForcePermissions(string module, string[] args) + { + if (m_scene.ConsoleScene() != null && + m_scene.ConsoleScene() != m_scene) + { + return; + } + + if (!m_bypassPermissions) + { + m_log.Error("[PERMISSIONS] Permissions can't be forced unless they are bypassed first"); + return; + } + + if (args.Length > 2) + { + bool val; + + if (!bool.TryParse(args[2], out val)) + return; + + m_bypassPermissionsValue = val; + + m_log.InfoFormat("[PERMISSIONS] Forced permissions to {0} in {1}", m_bypassPermissionsValue, m_scene.RegionInfo.RegionName); + } + } + + public void HandleDebugPermissions(string module, string[] args) + { + if (m_scene.ConsoleScene() != null && + m_scene.ConsoleScene() != m_scene) + { + return; + } + + if (args.Length > 2) + { + bool val; + + if (!bool.TryParse(args[2], out val)) + return; + + m_debugPermissions = val; + + m_log.InfoFormat("[PERMISSIONS] Set permissions debugging to {0} in {1}", m_debugPermissions, m_scene.RegionInfo.RegionName); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "PermissionsModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region Helper Functions + protected void SendPermissionError(UUID user, string reason) + { + m_scene.EventManager.TriggerPermissionError(user, reason); + } + + protected void DebugPermissionInformation(string permissionCalled) + { + if (m_debugPermissions) + m_log.Debug("[PERMISSIONS]: " + permissionCalled + " was called from " + m_scene.RegionInfo.RegionName); + } + + /// + /// Parse a user set configuration setting + /// + /// + /// + /// The default value for this attribute + /// The parsed value + private static UserSet ParseUserSetConfigSetting(IConfig config, string settingName, UserSet defaultValue) + { + UserSet userSet = defaultValue; + + string rawSetting = config.GetString(settingName, defaultValue.ToString()); + + // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term + // this should disappear. + if ("gods" == rawSetting.ToLower()) + rawSetting = UserSet.Administrators.ToString(); + + // Doing it this was so that we can do a case insensitive conversion + try + { + userSet = (UserSet)Enum.Parse(typeof(UserSet), rawSetting, true); + } + catch + { + m_log.ErrorFormat( + "[PERMISSIONS]: {0} is not a valid {1} value, setting to {2}", + rawSetting, settingName, userSet); + } + + m_log.DebugFormat("[PERMISSIONS]: {0} {1}", settingName, userSet); + + return userSet; + } + + /// + /// Is the given user an administrator (in other words, a god)? + /// + /// + /// + protected bool IsAdministrator(UUID user) + { + if (m_scene.RegionInfo.MasterAvatarAssignedUUID != UUID.Zero) + { + if (m_RegionOwnerIsGod && (m_scene.RegionInfo.MasterAvatarAssignedUUID == user)) + return true; + } + + if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) + { + if (m_scene.RegionInfo.EstateSettings.EstateOwner == user) + return true; + } + + if (m_allowGridGods) + { + CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(user); + if (profile != null && profile.UserProfile != null) + { + if (profile.UserProfile.GodLevel >= 200) + return true; + } + else + { + m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for administrator check", user); + } + } + + return false; + } + + protected bool IsEstateManager(UUID user) + { + return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); + } +#endregion + + public bool PropagatePermissions() + { + if (m_bypassPermissions) + return false; + + return m_propagatePermissions; + } + + public bool BypassPermissions() + { + return m_bypassPermissions; + } + + public void SetBypassPermissions(bool value) + { + m_bypassPermissions=value; + } + + #region Object Permissions + + public uint GenerateClientFlags(UUID user, UUID objID) + { + // Here's the way this works, + // ObjectFlags and Permission flags are two different enumerations + // ObjectFlags, however, tells the client to change what it will allow the user to do. + // So, that means that all of the permissions type ObjectFlags are /temporary/ and only + // supposed to be set when customizing the objectflags for the client. + + // These temporary objectflags get computed and added in this function based on the + // Permission mask that's appropriate! + // Outside of this method, they should never be added to objectflags! + // -teravus + + SceneObjectPart task = m_scene.GetSceneObjectPart(objID); + + // this shouldn't ever happen.. return no permissions/objectflags. + if (task == null) + return (uint)0; + + uint objflags = task.GetEffectiveObjectFlags(); + UUID objectOwner = task.OwnerID; + + + // Remove any of the objectFlags that are temporary. These will get added back if appropriate + // in the next bit of code + + // libomv will moan about PrimFlags.ObjectYouOfficer being + // deprecated + #pragma warning disable 0612 + objflags &= (uint) + ~(PrimFlags.ObjectCopy | // Tells client you can copy the object + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object + PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set + ); + #pragma warning restore 0612 + + // Creating the three ObjectFlags options for this method to choose from. + // Customize the OwnerMask + uint objectOwnerMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); + objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify; + + // Customize the GroupMask + // uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); + + // Customize the EveryoneMask + uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); + + + // Hack to allow collaboration until Groups and Group Permissions are implemented + if ((objectEveryoneMask & (uint)PrimFlags.ObjectMove) != 0) + objectEveryoneMask |= (uint)PrimFlags.ObjectModify; + + if (m_bypassPermissions) + return objectOwnerMask; + + // Object owners should be able to edit their own content + if (user == objectOwner) + { + return objectOwnerMask; + } + + // Users should be able to edit what is over their land. + ILandObject parcel = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); + if (parcel != null && parcel.landData.OwnerID == user && m_ParcelOwnerIsGod) + return objectOwnerMask; + + // Admin objects should not be editable by the above + if (IsAdministrator(objectOwner)) + return objectEveryoneMask; + + // Estate users should be able to edit anything in the sim + if (IsEstateManager(user) && m_RegionOwnerIsGod) + return objectOwnerMask; + + // Admin should be able to edit anything in the sim (including admin objects) + if (IsAdministrator(user)) + return objectOwnerMask; + + + return objectEveryoneMask; + } + + private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) + { + // We are adding the temporary objectflags to the object's objectflags based on the + // permission flag given. These change the F flags on the client. + + if ((setPermissionMask & (uint)PermissionMask.Copy) != 0) + { + objectFlagsMask |= (uint)PrimFlags.ObjectCopy; + } + + if ((setPermissionMask & (uint)PermissionMask.Move) != 0) + { + objectFlagsMask |= (uint)PrimFlags.ObjectMove; + } + + if ((setPermissionMask & (uint)PermissionMask.Modify) != 0) + { + objectFlagsMask |= (uint)PrimFlags.ObjectModify; + } + + if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0) + { + objectFlagsMask |= (uint)PrimFlags.ObjectTransfer; + } + + return objectFlagsMask; + } + + /// + /// General permissions checks for any operation involving an object. These supplement more specific checks + /// implemented by callers. + /// + /// + /// + /// + /// + protected bool GenericObjectPermission(UUID currentUser, UUID objId, bool denyOnLocked) + { + // Default: deny + bool permission = false; + bool locked = false; + + if (!m_scene.Entities.ContainsKey(objId)) + { + return false; + } + + // If it's not an object, we cant edit it. + if ((!(m_scene.Entities[objId] is SceneObjectGroup))) + { + return false; + } + + SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objId]; + + UUID objectOwner = group.OwnerID; + locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); + + // People shouldn't be able to do anything with locked objects, except the Administrator + // The 'set permissions' runs through a different permission check, so when an object owner + // sets an object locked, the only thing that they can do is unlock it. + // + // Nobody but the object owner can set permissions on an object + // + + if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) + { + return false; + } + + // Object owners should be able to edit their own content + if (currentUser == objectOwner) + { + permission = true; + } + else if (group.IsAttachment) + { + permission = false; + } + + // Users should be able to edit what is over their land. + ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); + if ((parcel != null) && (parcel.landData.OwnerID == currentUser)) + { + permission = true; + } + + // Estate users should be able to edit anything in the sim + if (IsEstateManager(currentUser)) + { + permission = true; + } + + // Admin objects should not be editable by the above + if (IsAdministrator(objectOwner)) + { + permission = false; + } + + // Admin should be able to edit anything in the sim (including admin objects) + if (IsAdministrator(currentUser)) + { + permission = true; + } + + return permission; + } + + #endregion + + #region Generic Permissions + protected bool GenericCommunicationPermission(UUID user, UUID target) + { + // Setting this to true so that cool stuff can happen until we define what determines Generic Communication Permission + bool permission = true; + string reason = "Only registered users may communicate with another account."; + + // Uhh, we need to finish this before we enable it.. because it's blocking all sorts of goodies and features + if (IsAdministrator(user)) + permission = true; + + if (IsEstateManager(user)) + permission = true; + + if (!permission) + SendPermissionError(user, reason); + + return permission; + } + + public bool GenericEstatePermission(UUID user) + { + // Default: deny + bool permission = false; + + // Estate admins should be able to use estate tools + if (IsEstateManager(user)) + permission = true; + + // Administrators always have permission + if (IsAdministrator(user)) + permission = true; + + return permission; + } + + protected bool GenericParcelPermission(UUID user, ILandObject parcel) + { + bool permission = false; + + if (parcel.landData.OwnerID == user) + { + permission = true; + } + + if (parcel.landData.IsGroupOwned) + { + // TODO: Need to do some extra checks here. Requires group code. + } + + if (IsEstateManager(user)) + { + permission = true; + } + + if (IsAdministrator(user)) + { + permission = true; + } + + return permission; + } + + protected bool GenericParcelPermission(UUID user, Vector3 pos) + { + ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (parcel == null) return false; + return GenericParcelPermission(user, parcel); + } +#endregion + + #region Permission Checks + private bool CanAbandonParcel(UUID user, ILandObject parcel, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericParcelPermission(user, parcel); + } + + private bool CanReclaimParcel(UUID user, ILandObject parcel, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericParcelPermission(user, parcel); + } + + private bool IsGod(UUID user, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return IsAdministrator(user); + } + + private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (!GenericObjectPermission(owner, objectID, true)) + { + //They can't even edit the object + return false; + } + + SceneObjectPart part = scene.GetSceneObjectPart(objectID); + if (part == null) + return false; + + if ((part.OwnerMask & PERM_COPY) == 0) + return false; + + if ((part.ParentGroup.GetEffectivePermissions() & PERM_COPY) == 0) + return false; + + //If they can rez, they can duplicate + return CanRezObject(objectCount, owner, objectPosition, scene); + } + + private bool CanDeleteObject(UUID objectID, UUID deleter, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericObjectPermission(deleter, objectID, false); + } + + private bool CanEditObject(UUID objectID, UUID editorID, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + + return GenericObjectPermission(editorID, objectID, false); + } + + private bool CanEditObjectInventory(UUID objectID, UUID editorID, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + + // If we selected a sub-prim to edit, the objectID won't represent the object, but only a part. + // We have to check the permissions of the group, though. + if (part.ParentID != 0) + { + objectID = part.ParentUUID; + part = m_scene.GetSceneObjectPart(objectID); + } + + // TODO: add group support! + // + if (part.OwnerID != editorID) + return false; + + return GenericObjectPermission(editorID, objectID, false); + } + + private bool CanEditParcel(UUID user, ILandObject parcel, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericParcelPermission(user, parcel); + } + + /// + /// Check whether the specified user can edit the given script + /// + /// + /// + /// + /// + /// + private bool CanEditScript(UUID script, UUID objectID, UUID user, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(user)) + return false; + + // Ordinarily, if you can view it, you can edit it + // There is no viewing a no mod script + // + return CanViewScript(script, objectID, user, scene); + } + + /// + /// Check whether the specified user can edit the given notecard + /// + /// + /// + /// + /// + /// + private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (objectID == UUID.Zero) // User inventory + { + CachedUserInfo userInfo = + scene.CommsManager.UserProfileCacheService.GetUserDetails(user); + + if (userInfo == null) + { + m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for edit notecard check", user); + return false; + } + + if (userInfo.RootFolder == null) + return false; + + InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(notecard); + if (assetRequestItem == null) // Library item + { + assetRequestItem = scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(notecard); + + if (assetRequestItem != null) // Implicitly readable + return true; + } + + // Notecards must be both mod and copy to be saveable + // This is because of they're not copy, you can't read + // them, and if they're not mod, well, then they're + // not mod. Duh. + // + if ((assetRequestItem.CurrentPermissions & + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy)) != + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy)) + return false; + } + else // Prim inventory + { + SceneObjectPart part = scene.GetSceneObjectPart(objectID); + + if (part == null) + return false; + + if (part.OwnerID != user) + return false; + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + return false; + + TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); + + if (ti == null) + return false; + + if (ti.OwnerID != user) + return false; + + // Require full perms + if ((ti.CurrentPermissions & + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy)) != + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy)) + return false; + } + + return true; + } + + private bool CanInstantMessage(UUID user, UUID target, Scene startScene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + // If the sender is an object, check owner instead + // + SceneObjectPart part = startScene.GetSceneObjectPart(user); + if (part != null) + user = part.OwnerID; + + return GenericCommunicationPermission(user, target); + } + + private bool CanInventoryTransfer(UUID user, UUID target, Scene startScene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericCommunicationPermission(user, target); + } + + private bool CanIssueEstateCommand(UUID user, Scene requestFromScene, bool ownerCommand) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (IsAdministrator(user)) + return true; + + if (m_scene.RegionInfo.EstateSettings.IsEstateOwner(user)) + return true; + + if (ownerCommand) + return false; + + return GenericEstatePermission(user); + } + + private bool CanMoveObject(UUID objectID, UUID moverID, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) + { + SceneObjectPart part = scene.GetSceneObjectPart(objectID); + if (part.OwnerID != moverID) + { + if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) + { + if (part.ParentGroup.IsAttachment) + return false; + } + } + return m_bypassPermissionsValue; + } + + bool permission = GenericObjectPermission(moverID, objectID, true); + if (!permission) + { + if (!m_scene.Entities.ContainsKey(objectID)) + { + return false; + } + + // The client + // may request to edit linked parts, and therefore, it needs + // to also check for SceneObjectPart + + // If it's not an object, we cant edit it. + if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) + { + return false; + } + + + SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; + + + // UUID taskOwner = null; + // Added this because at this point in time it wouldn't be wise for + // the administrator object permissions to take effect. + // UUID objectOwner = task.OwnerID; + + // Anyone can move + if ((task.RootPart.EveryoneMask & PERM_MOVE) != 0) + permission = true; + + // Locked + if ((task.RootPart.OwnerMask & PERM_LOCKED) == 0) + permission = false; + } + else + { + bool locked = false; + if (!m_scene.Entities.ContainsKey(objectID)) + { + return false; + } + + // If it's not an object, we cant edit it. + if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) + { + return false; + } + + SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objectID]; + + UUID objectOwner = group.OwnerID; + locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); + + // This is an exception to the generic object permission. + // Administrators who lock their objects should not be able to move them, + // however generic object permission should return true. + // This keeps locked objects from being affected by random click + drag actions by accident + // and allows the administrator to grab or delete a locked object. + + // Administrators and estate managers are still able to click+grab locked objects not + // owned by them in the scene + // This is by design. + + if (locked && (moverID == objectOwner)) + return false; + } + return permission; + } + + private bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if ((newPoint.X > 257f || newPoint.X < -1f || newPoint.Y > 257f || newPoint.Y < -1f)) + { + return true; + } + + SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; + + ILandObject land = m_scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); + + if (!enteringRegion) + { + ILandObject fromland = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); + + if (fromland == land) // Not entering + return true; + } + + if (land == null) + { + return false; + } + + if ((land.landData.Flags & ((int)Parcel.ParcelFlags.AllowAPrimitiveEntry)) != 0) + { + return true; + } + + //TODO: check for group rights + + if (!m_scene.Entities.ContainsKey(objectID)) + { + return false; + } + + // If it's not an object, we cant edit it. + if (!(m_scene.Entities[objectID] is SceneObjectGroup)) + { + return false; + } + + + if (GenericParcelPermission(task.OwnerID, newPoint)) + { + return true; + } + + //Otherwise, false! + return false; + } + + private bool CanReturnObject(UUID objectID, UUID returnerID, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericObjectPermission(returnerID, objectID, false); + } + + private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + bool permission = false; + + ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); + if (land == null) return false; + + if ((land.landData.Flags & ((int)Parcel.ParcelFlags.CreateObjects)) == + (int)Parcel.ParcelFlags.CreateObjects) + permission = true; + + //TODO: check for group rights + + if (IsAdministrator(owner)) + { + permission = true; + } + + if (GenericParcelPermission(owner, objectPosition)) + { + permission = true; + } + + return permission; + } + + private bool CanRunConsoleCommand(UUID user, Scene requestFromScene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + + return IsAdministrator(user); + } + + private bool CanRunScript(UUID script, UUID objectID, UUID user, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + private bool CanSellParcel(UUID user, ILandObject parcel, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericParcelPermission(user, parcel); + } + + private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericObjectPermission(stealer,objectID, false); + } + + private bool CanTakeCopyObject(UUID objectID, UUID userID, Scene inScene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + bool permission = GenericObjectPermission(userID, objectID,false); + if (!permission) + { + if (!m_scene.Entities.ContainsKey(objectID)) + { + return false; + } + + // If it's not an object, we cant edit it. + if (!(m_scene.Entities[objectID] is SceneObjectGroup)) + { + return false; + } + + SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; + // UUID taskOwner = null; + // Added this because at this point in time it wouldn't be wise for + // the administrator object permissions to take effect. + // UUID objectOwner = task.OwnerID; + + if ((task.RootPart.EveryoneMask & PERM_COPY) != 0) + permission = true; + + if ((task.GetEffectivePermissions() & PERM_COPY) == 0) + permission = false; + } + else + { + SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; + + if ((task.GetEffectivePermissions() & PERM_COPY) == 0) + permission = false; + } + + return permission; + } + + private bool CanTerraformLand(UUID user, Vector3 position, Scene requestFromScene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + // Estate override + if (GenericEstatePermission(user)) + return true; + + float X = position.X; + float Y = position.Y; + + if (X > 255) + X = 255; + if (Y > 255) + Y = 255; + if (X < 0) + X = 0; + if (Y < 0) + Y = 0; + + ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y); + if (parcel == null) + return false; + + // Others allowed to terraform? + if ((parcel.landData.Flags & ((int)Parcel.ParcelFlags.AllowTerraform)) != 0) + return true; + + // Land owner can terraform too + if (parcel != null && GenericParcelPermission(user, parcel)) + return true; + + return false; + } + + /// + /// Check whether the specified user can view the given script + /// + /// + /// + /// + /// + /// + private bool CanViewScript(UUID script, UUID objectID, UUID user, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (objectID == UUID.Zero) // User inventory + { + CachedUserInfo userInfo = + scene.CommsManager.UserProfileCacheService.GetUserDetails(user); + + if (userInfo == null) + { + m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for administrator check", user); + return false; + } + + if (userInfo.RootFolder == null) + return false; + + InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(script); + if (assetRequestItem == null) // Library item + { + assetRequestItem = m_scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(script); + + if (assetRequestItem != null) // Implicitly readable + return true; + } + + // SL is rather harebrained here. In SL, a script you + // have mod/copy no trans is readable. This subverts + // permissions, but is used in some products, most + // notably Hippo door plugin and HippoRent 5 networked + // prim counter. + // To enable this broken SL-ism, remove Transfer from + // the below expressions. + // Trying to improve on SL perms by making a script + // readable only if it's really full perms + // + if ((assetRequestItem.CurrentPermissions & + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer)) != + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer)) + return false; + } + else // Prim inventory + { + SceneObjectPart part = scene.GetSceneObjectPart(objectID); + + if (part == null) + return false; + + if (part.OwnerID != user) + return false; + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + return false; + + TaskInventoryItem ti = part.Inventory.GetInventoryItem(script); + + if (ti == null) + return false; + + if (ti.OwnerID != user) + return false; + + // Require full perms + if ((ti.CurrentPermissions & + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer)) != + ((uint)PermissionMask.Modify | + (uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer)) + return false; + } + + return true; + } + + /// + /// Check whether the specified user can view the given notecard + /// + /// + /// + /// + /// + /// + private bool CanViewNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (objectID == UUID.Zero) // User inventory + { + CachedUserInfo userInfo = + scene.CommsManager.UserProfileCacheService.GetUserDetails(user); + + if (userInfo == null) + { + m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for view notecard check", user); + return false; + } + + if (userInfo.RootFolder == null) + return false; + + InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(notecard); + if (assetRequestItem == null) // Library item + { + assetRequestItem = m_scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(notecard); + + if (assetRequestItem != null) // Implicitly readable + return true; + } + + // Notecards are always readable unless no copy + // + if ((assetRequestItem.CurrentPermissions & + (uint)PermissionMask.Copy) != + (uint)PermissionMask.Copy) + return false; + } + else // Prim inventory + { + SceneObjectPart part = scene.GetSceneObjectPart(objectID); + + if (part == null) + return false; + + if (part.OwnerID != user) + return false; + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + return false; + + TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); + + if (ti == null) + return false; + + if (ti.OwnerID != user) + return false; + + // Notecards are always readable unless no copy + // + if ((ti.CurrentPermissions & + (uint)PermissionMask.Copy) != + (uint)PermissionMask.Copy) + return false; + } + + return true; + } + + #endregion + + private bool CanLinkObject(UUID userID, UUID objectID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + private bool CanDelinkObject(UUID userID, UUID objectID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + private bool CanCopyObjectInventory(UUID itemID, UUID objectID, UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + private bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + /// + /// Check whether the specified user is allowed to directly create the given inventory type in a prim's + /// inventory (e.g. the New Script button in the 1.21 Linden Lab client). + /// + /// + /// + /// + /// + private bool CanCreateObjectInventory(int invType, UUID objectID, UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if ((int)InventoryType.LSL == invType) + if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID)) + return false; + + return true; + } + + /// + /// Check whether the specified user is allowed to create the given inventory type in their inventory. + /// + /// + /// + /// + private bool CanCreateUserInventory(int invType, UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if ((int)InventoryType.LSL == invType) + if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID)) + return false; + + return true; + } + + /// + /// Check whether the specified user is allowed to copy the given inventory type in their inventory. + /// + /// + /// + /// + private bool CanCopyUserInventory(UUID itemID, UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + /// + /// Check whether the specified user is allowed to edit the given inventory item within their own inventory. + /// + /// + /// + /// + private bool CanEditUserInventory(UUID itemID, UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + /// + /// Check whether the specified user is allowed to delete the given inventory item from their own inventory. + /// + /// + /// + /// + private bool CanDeleteUserInventory(UUID itemID, UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + private bool CanTeleport(UUID userID) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return true; + } + + private bool CanResetScript(UUID prim, UUID script, UUID agentID, Scene scene) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + SceneObjectPart part = m_scene.GetSceneObjectPart(prim); + + // If we selected a sub-prim to reset, prim won't represent the object, but only a part. + // We have to check the permissions of the object, though. + if (part.ParentID != 0) prim = part.ParentUUID; + + // You can reset the scripts in any object you can edit + return GenericObjectPermission(agentID, prim, false); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Serialiser/IFileSerialiser.cs b/OpenSim/Region/CoreModules/World/Serialiser/IFileSerialiser.cs new file mode 100644 index 0000000..acc7bb8 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Serialiser/IFileSerialiser.cs @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Serialiser +{ + internal interface IFileSerialiser + { + string WriteToFile(Scene scene, string dir); + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs new file mode 100644 index 0000000..ed6448f --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseObjects.cs @@ -0,0 +1,125 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Text; +using System.Xml; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Serialiser +{ + internal class SerialiseObjects : IFileSerialiser + { + #region IFileSerialiser Members + + public string WriteToFile(Scene scene, string dir) + { + string targetFileName = dir + "objects.xml"; + + SaveSerialisedToFile(targetFileName, scene); + + return "objects.xml"; + } + + #endregion + + public void SaveSerialisedToFile(string fileName, Scene scene) + { + string xmlstream = GetObjectXml(scene); + + MemoryStream stream = ReformatXmlString(xmlstream); + + stream.Seek(0, SeekOrigin.Begin); + CreateXmlFile(stream, fileName); + + stream.Seek(0, SeekOrigin.Begin); + CreateCompressedXmlFile(stream, fileName); + } + + private static MemoryStream ReformatXmlString(string xmlstream) + { + MemoryStream stream = new MemoryStream(); + XmlTextWriter formatter = new XmlTextWriter(stream, Encoding.UTF8); + XmlDocument doc = new XmlDocument(); + + doc.LoadXml(xmlstream); + formatter.Formatting = Formatting.Indented; + doc.WriteContentTo(formatter); + formatter.Flush(); + return stream; + } + + private static string GetObjectXml(Scene scene) + { + string xmlstream = ""; + + List EntityList = scene.GetEntities(); + List EntityXml = new List(); + + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + EntityXml.Add(((SceneObjectGroup) ent).ToXmlString2()); + } + } + EntityXml.Sort(); + + foreach (string xml in EntityXml) + xmlstream += xml; + + xmlstream += ""; + return xmlstream; + } + + private static void CreateXmlFile(MemoryStream xmlStream, string fileName) + { + FileStream objectsFile = new FileStream(fileName, FileMode.Create); + + xmlStream.WriteTo(objectsFile); + objectsFile.Flush(); + objectsFile.Close(); + } + + private static void CreateCompressedXmlFile(MemoryStream xmlStream, string fileName) + { + #region GZip Compressed Version + + FileStream objectsFileCompressed = new FileStream(fileName + ".gzs", FileMode.Create); + MemoryStream gzipMSStream = new MemoryStream(); + GZipStream gzipStream = new GZipStream(gzipMSStream, CompressionMode.Compress); + xmlStream.WriteTo(gzipStream); + gzipMSStream.WriteTo(objectsFileCompressed); + objectsFileCompressed.Flush(); + objectsFileCompressed.Close(); + + #endregion + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiseTerrain.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseTerrain.cs new file mode 100644 index 0000000..924218a --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiseTerrain.cs @@ -0,0 +1,53 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Serialiser +{ + internal class SerialiseTerrain : IFileSerialiser + { + #region IFileSerialiser Members + + public string WriteToFile(Scene scene, string dir) + { + ITerrainLoader fileSystemExporter = new RAW32(); + string targetFileName = dir + "heightmap.r32"; + + lock (scene.Heightmap) + { + fileSystemExporter.SaveFile(targetFileName, scene.Heightmap); + } + + return "heightmap.r32"; + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs new file mode 100644 index 0000000..7080d5f --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs @@ -0,0 +1,226 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using OpenMetaverse; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.Framework.InterfaceCommander; + +namespace OpenSim.Region.CoreModules.World.Serialiser +{ + public class SerialiserModule : IRegionModule, IRegionSerialiserModule + { + private Commander m_commander = new Commander("export"); + private List m_regions = new List(); + private string m_savedir = "exports" + "/"; + private List m_serialisers = new List(); + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + scene.RegisterModuleCommander(m_commander); + scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; + scene.RegisterModuleInterface(this); + + lock (m_regions) + { + m_regions.Add(scene); + } + } + + public void PostInitialise() + { + lock (m_serialisers) + { + m_serialisers.Add(new SerialiseTerrain()); + m_serialisers.Add(new SerialiseObjects()); + } + + LoadCommanderCommands(); + } + + public void Close() + { + m_regions.Clear(); + } + + public string Name + { + get { return "ExportSerialisationModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region IRegionSerialiser Members + + public void LoadPrimsFromXml(Scene scene, string fileName, bool newIDS, Vector3 loadOffset) + { + SceneXmlLoader.LoadPrimsFromXml(scene, fileName, newIDS, loadOffset); + } + + public void SavePrimsToXml(Scene scene, string fileName) + { + SceneXmlLoader.SavePrimsToXml(scene, fileName); + } + + public void LoadPrimsFromXml2(Scene scene, string fileName) + { + SceneXmlLoader.LoadPrimsFromXml2(scene, fileName); + } + + public void LoadPrimsFromXml2(Scene scene, TextReader reader, bool startScripts) + { + SceneXmlLoader.LoadPrimsFromXml2(scene, reader, startScripts); + } + + public void SavePrimsToXml2(Scene scene, string fileName) + { + SceneXmlLoader.SavePrimsToXml2(scene, fileName); + } + + public void SavePrimsToXml2(Scene scene, TextWriter stream, Vector3 min, Vector3 max) + { + SceneXmlLoader.SavePrimsToXml2(scene, stream, min, max); + } + + public void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName) + { + SceneXmlLoader.SaveNamedPrimsToXml2(scene, primName, fileName); + } + + public SceneObjectGroup DeserializeGroupFromXml2(string xmlString) + { + return SceneXmlLoader.DeserializeGroupFromXml2(xmlString); + } + + public string SaveGroupToXml2(SceneObjectGroup grp) + { + return SceneXmlLoader.SaveGroupToXml2(grp); + } + + public void SavePrimListToXml2(List entityList, string fileName) + { + SceneXmlLoader.SavePrimListToXml2(entityList, fileName); + } + + public void SavePrimListToXml2(List entityList, TextWriter stream, Vector3 min, Vector3 max) + { + SceneXmlLoader.SavePrimListToXml2(entityList, stream, min, max); + } + + public List SerialiseRegion(Scene scene, string saveDir) + { + List results = new List(); + + if (!Directory.Exists(saveDir)) + { + Directory.CreateDirectory(saveDir); + } + + lock (m_serialisers) + { + foreach (IFileSerialiser serialiser in m_serialisers) + { + results.Add(serialiser.WriteToFile(scene, saveDir)); + } + } + + TextWriter regionInfoWriter = new StreamWriter(saveDir + "README.TXT"); + regionInfoWriter.WriteLine("Region Name: " + scene.RegionInfo.RegionName); + regionInfoWriter.WriteLine("Region ID: " + scene.RegionInfo.RegionID.ToString()); + regionInfoWriter.WriteLine("Backup Time: UTC " + DateTime.UtcNow.ToString()); + regionInfoWriter.WriteLine("Serialise Version: 0.1"); + regionInfoWriter.Close(); + + TextWriter manifestWriter = new StreamWriter(saveDir + "region.manifest"); + foreach (string line in results) + { + manifestWriter.WriteLine(line); + } + manifestWriter.Close(); + + return results; + } + + #endregion + + private void EventManager_OnPluginConsole(string[] args) + { + if (args[0] == "export") + { + string[] tmpArgs = new string[args.Length - 2]; + int i = 0; + for (i = 2; i < args.Length; i++) + tmpArgs[i - 2] = args[i]; + + m_commander.ProcessConsoleCommand(args[1], tmpArgs); + } + } + + private void InterfaceSaveRegion(Object[] args) + { + foreach (Scene region in m_regions) + { + if (region.RegionInfo.RegionName == (string) args[0]) + { + // List results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); + SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); + } + } + } + + private void InterfaceSaveAllRegions(Object[] args) + { + foreach (Scene region in m_regions) + { + // List results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); + SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); + } + } + + private void LoadCommanderCommands() + { + Command serialiseSceneCommand = new Command("save", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveRegion, "Saves the named region into the exports directory."); + serialiseSceneCommand.AddArgument("region-name", "The name of the region you wish to export", "String"); + + Command serialiseAllScenesCommand = new Command("save-all",CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveAllRegions, "Saves all regions into the exports directory."); + + m_commander.RegisterCommand("save", serialiseSceneCommand); + m_commander.RegisterCommand("save-all", serialiseAllScenesCommand); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs new file mode 100644 index 0000000..ffd6b8d --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -0,0 +1,97 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using Nini.Config; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Sound +{ + public class SoundModule : IRegionModule, ISoundModule + { + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + + m_scene.EventManager.OnNewClient += OnNewClient; + + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() {} + public void Close() {} + public string Name { get { return "Sound Module"; } } + public bool IsSharedModule { get { return false; } } + + private void OnNewClient(IClientAPI client) + { + client.OnSoundTrigger += TriggerSound; + } + + public virtual void PlayAttachedSound( + UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags) + { + foreach (ScenePresence p in m_scene.GetAvatars()) + { + double dis = Util.GetDistanceTo(p.AbsolutePosition, position); + if (dis > 100.0) // Max audio distance + continue; + + // Scale by distance + gain = (float)((double)gain*((100.0 - dis) / 100.0)); + + p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); + } + } + + public virtual void TriggerSound( + UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle) + { + foreach (ScenePresence p in m_scene.GetAvatars()) + { + double dis = Util.GetDistanceTo(p.AbsolutePosition, position); + if (dis > 100.0) // Max audio distance + continue; + + // Scale by distance + gain = (float)((double)gain*((100.0 - dis) / 100.0)); + + p.ControllingClient.SendTriggeredSound( + soundId, ownerID, objectID, parentID, handle, position, (float)gain); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs new file mode 100644 index 0000000..b36684c --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs @@ -0,0 +1,434 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules +{ + public class SunModule : IRegionModule + { + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private const double SeasonalTilt = 0.03 * Math.PI; // A daily shift of approximately 1.7188 degrees + private const double AverageTilt = -0.25 * Math.PI; // A 45 degree tilt + private const double SunCycle = 2.0D * Math.PI; // A perfect circle measured in radians + private const double SeasonalCycle = 2.0D * Math.PI; // Ditto + + // + // Per Region Values + // + + private bool ready = false; + + // Configurable values + private string m_mode = "SL"; + private int m_frame_mod = 0; + private double m_day_length = 0; + private int m_year_length = 0; + private double m_day_night = 0; + // private double m_longitude = 0; + // private double m_latitude = 0; + // Configurable defaults Defaults close to SL + private string d_mode = "SL"; + private int d_frame_mod = 100; // Every 10 seconds (actually less) + private double d_day_length = 4; // A VW day is 4 RW hours long + private int d_year_length = 60; // There are 60 VW days in a VW year + private double d_day_night = 0.45; // axis offset: ratio of light-to-dark, approx 1:3 + // private double d_longitude = -73.53; + // private double d_latitude = 41.29; + + // Frame counter + private uint m_frame = 0; + + // Cached Scene reference + private Scene m_scene = null; + + // Calculated Once in the lifetime of a region + private long TicksToEpoch; // Elapsed time for 1/1/1970 + private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds + private uint SecondsPerYear; // Length of a virtual year in RW seconds + private double SunSpeed; // Rate of passage in radians/second + private double SeasonSpeed; // Rate of change for seasonal effects + // private double HoursToRadians; // Rate of change for seasonal effects + private long TicksOffset = 0; // seconds offset from UTC + // Calculated every update + private float OrbitalPosition; // Orbital placement at a point in time + private double HorizonShift; // Axis offset to skew day and night + private double TotalDistanceTravelled; // Distance since beginning of time (in radians) + private double SeasonalOffset; // Seaonal variation of tilt + private float Magnitude; // Normal tilt + // private double VWTimeRatio; // VW time as a ratio of real time + + // Working values + private Vector3 Position = Vector3.Zero; + private Vector3 Velocity = Vector3.Zero; + private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f); + + private long LindenHourOffset = 0; + private bool sunFixed = false; + + private Dictionary m_rootAgents = new Dictionary(); + + // Current time in elapsed seconds since Jan 1st 1970 + private ulong CurrentTime + { + get { + return (ulong)(((System.DateTime.Now.Ticks) - TicksToEpoch + TicksOffset + LindenHourOffset)/10000000); + } + } + + private float GetLindenEstateHourFromCurrentTime() + { + float ticksleftover = ((float)CurrentTime) % ((float)SecondsPerSunCycle); + + float hour = (24 * (ticksleftover / SecondsPerSunCycle)) + 6; + + return hour; + } + + private void SetTimeByLindenHour(float LindenHour) + { + // Linden hour is 24 hours with a 6 hour offset. 6-30 + + if (LindenHour - 6 == 0) + { + LindenHourOffset = 0; + return; + } + + // Remove LindenHourOffset to calculate it from LocalTime + float ticksleftover = ((float)(((long)(CurrentTime * 10000000) - (long)LindenHourOffset)/ 10000000) % ((float)SecondsPerSunCycle)); + float hour = (24 * (ticksleftover / SecondsPerSunCycle)); + + float offsethours = 0; + + if (LindenHour - 6 > hour) + { + offsethours = hour + ((LindenHour-6) - hour); + } + else + { + offsethours = hour - (hour - (LindenHour - 6)); + } + //m_log.Debug("[OFFSET]: " + hour + " - " + LindenHour + " - " + offsethours.ToString()); + + LindenHourOffset = (long)((float)offsethours * (36000000000/m_day_length)); + m_log.Debug("[SUN]: Directive from the Estate Tools to set the sun phase to LindenHour " + GetLindenEstateHourFromCurrentTime().ToString()); + } + + // Called immediately after the module is loaded for a given region + // i.e. Immediately after instance creation. + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + + m_frame = 0; + + TimeZone local = TimeZone.CurrentTimeZone; + TicksOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks; + m_log.Debug("[SUN]: localtime offset is " + TicksOffset); + + // Align ticks with Second Life + + TicksToEpoch = new System.DateTime(1970,1,1).Ticks; + + // Just in case they don't have the stanzas + try + { + // Mode: determines how the sun is handled + m_mode = config.Configs["Sun"].GetString("mode", d_mode); + // Mode: determines how the sun is handled + // m_latitude = config.Configs["Sun"].GetDouble("latitude", d_latitude); + // Mode: determines how the sun is handled + // m_longitude = config.Configs["Sun"].GetDouble("longitude", d_longitude); + // Year length in days + m_year_length = config.Configs["Sun"].GetInt("year_length", d_year_length); + // Day length in decimal hours + m_day_length = config.Configs["Sun"].GetDouble("day_length", d_day_length); + // Day to Night Ratio + m_day_night = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night); + // Update frequency in frames + m_frame_mod = config.Configs["Sun"].GetInt("update_interval", d_frame_mod); + } + catch (Exception e) + { + m_log.Debug("[SUN]: Configuration access failed, using defaults. Reason: "+e.Message); + m_mode = d_mode; + m_year_length = d_year_length; + m_day_length = d_day_length; + m_day_night = d_day_night; + m_frame_mod = d_frame_mod; + // m_latitude = d_latitude; + // m_longitude = d_longitude; + } + + switch (m_mode) + { + case "T1": + default: + case "SL": + // Time taken to complete a cycle (day and season) + + SecondsPerSunCycle = (uint) (m_day_length * 60 * 60); + SecondsPerYear = (uint) (SecondsPerSunCycle*m_year_length); + + // Ration of real-to-virtual time + + // VWTimeRatio = 24/m_day_length; + + // Speed of rotation needed to complete a cycle in the + // designated period (day and season) + + SunSpeed = SunCycle/SecondsPerSunCycle; + SeasonSpeed = SeasonalCycle/SecondsPerYear; + + // Horizon translation + + HorizonShift = m_day_night; // Z axis translation + // HoursToRadians = (SunCycle/24)*VWTimeRatio; + + // Insert our event handling hooks + + scene.EventManager.OnFrame += SunUpdate; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; + scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; + scene.EventManager.OnClientClosed += ClientLoggedOut; + scene.EventManager.OnEstateToolsTimeUpdate += EstateToolsTimeUpdate; + scene.EventManager.OnGetSunLindenHour += GetLindenEstateHourFromCurrentTime; + + ready = true; + + m_log.Debug("[SUN]: Mode is "+m_mode); + m_log.Debug("[SUN]: Initialization completed. Day is "+SecondsPerSunCycle+" seconds, and year is "+m_year_length+" days"); + m_log.Debug("[SUN]: Axis offset is "+m_day_night); + m_log.Debug("[SUN]: Positional data updated every "+m_frame_mod+" frames"); + + break; + } + } + + public void PostInitialise() + { + } + + public void Close() + { + ready = false; + + // Remove our hooks + m_scene.EventManager.OnFrame -= SunUpdate; + m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent; + m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; + m_scene.EventManager.OnClientClosed -= ClientLoggedOut; + m_scene.EventManager.OnEstateToolsTimeUpdate -= EstateToolsTimeUpdate; + m_scene.EventManager.OnGetSunLindenHour -= GetLindenEstateHourFromCurrentTime; + } + + public string Name + { + get { return "SunModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void SunToClient(IClientAPI client) + { + if (m_mode != "T1") + { + if (ready) + { + if (!sunFixed) + GenSunPos(); // Generate shared values once + client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); + } + } + } + + public void SunUpdate() + { + if (((m_frame++%m_frame_mod) != 0) || !ready || sunFixed) + { + return; + } + + GenSunPos(); // Generate shared values once + + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence avatar in avatars) + { + if (!avatar.IsChildAgent) + avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); + } + + // set estate settings for region access to sun position + m_scene.RegionInfo.RegionSettings.SunVector = Position; + //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime(); + } + + public void ForceSunUpdateToAllClients() + { + GenSunPos(); // Generate shared values once + + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence avatar in avatars) + { + if (!avatar.IsChildAgent) + avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); + } + + // set estate settings for region access to sun position + m_scene.RegionInfo.RegionSettings.SunVector = Position; + m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime(); + } + + /// + /// Calculate the sun's orbital position and its velocity. + /// + private void GenSunPos() + { + TotalDistanceTravelled = SunSpeed * CurrentTime; // distance measured in radians + OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); // position measured in radians + + // TotalDistanceTravelled += HoursToRadians-(0.25*Math.PI)*Math.Cos(HoursToRadians)-OrbitalPosition; + // OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); + + SeasonalOffset = SeasonSpeed * CurrentTime; // Present season determined as total radians travelled around season cycle + + Tilt.W = (float) (AverageTilt + (SeasonalTilt*Math.Sin(SeasonalOffset))); // Calculate seasonal orbital N/S tilt + + // m_log.Debug("[SUN] Total distance travelled = "+TotalDistanceTravelled+", present position = "+OrbitalPosition+"."); + // m_log.Debug("[SUN] Total seasonal progress = "+SeasonalOffset+", present tilt = "+Tilt.W+"."); + + // The sun rotates about the Z axis + + Position.X = (float) Math.Cos(-TotalDistanceTravelled); + Position.Y = (float) Math.Sin(-TotalDistanceTravelled); + Position.Z = 0; + + // For interest we rotate it slightly about the X access. + // Celestial tilt is a value that ranges .025 + + Position *= Tilt; + + // Finally we shift the axis so that more of the + // circle is above the horizon than below. This + // makes the nights shorter than the days. + + Position.Z = Position.Z + (float) HorizonShift; + Position = Vector3.Normalize(Position); + + // m_log.Debug("[SUN] Position("+Position.X+","+Position.Y+","+Position.Z+")"); + + Velocity.X = 0; + Velocity.Y = 0; + Velocity.Z = (float) SunSpeed; + + // Correct angular velocity to reflect the seasonal rotation + + Magnitude = Position.Length(); + if (sunFixed) + { + Velocity.X = 0; + Velocity.Y = 0; + Velocity.Z = 0; + return; + } + + Velocity = (Velocity * Tilt) * (1.0f / Magnitude); + + // m_log.Debug("[SUN] Velocity("+Velocity.X+","+Velocity.Y+","+Velocity.Z+")"); + } + + private void ClientLoggedOut(UUID AgentId) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(AgentId)) + { + m_rootAgents.Remove(AgentId); + } + } + } + + private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + m_rootAgents[avatar.UUID] = avatar.RegionHandle; + } + else + { + m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); + SunToClient(avatar.ControllingClient); + } + } + //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); + } + + private void MakeChildAgent(ScenePresence avatar) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) + { + m_rootAgents.Remove(avatar.UUID); + } + } + } + } + + public void EstateToolsTimeUpdate(ulong regionHandle, bool FixedTime, bool useEstateTime, float LindenHour) + { + if (m_scene.RegionInfo.RegionHandle == regionHandle) + { + SetTimeByLindenHour(LindenHour); + + //if (useEstateTime) + //LindenHourOffset = 0; + + ForceSunUpdateToAllClients(); + sunFixed = FixedTime; + if (sunFixed) + GenSunPos(); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/DefaultEffects/ChannelDigger.cs b/OpenSim/Region/CoreModules/World/Terrain/DefaultEffects/ChannelDigger.cs new file mode 100644 index 0000000..f96ab88 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/DefaultEffects/ChannelDigger.cs @@ -0,0 +1,107 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; + +namespace OpenSim.Region.Modules.Terrain.Extensions.DefaultEffects.Effects +{ + public class ChannelDigger : ITerrainEffect + { + private readonly int num_h = 4; + private readonly int num_w = 4; + + private readonly ITerrainFloodEffect raiseFunction = new RaiseArea(); + private readonly ITerrainFloodEffect smoothFunction = new SmoothArea(); + + #region ITerrainEffect Members + + public void RunEffect(ITerrainChannel map) + { + FillMap(map, 15); + BuildTiles(map, 7); + SmoothMap(map, 3); + } + + #endregion + + private void SmoothMap(ITerrainChannel map, int rounds) + { + Boolean[,] bitmap = new bool[map.Width,map.Height]; + for (int x = 0; x < map.Width; x++) + { + for (int y = 0; y < map.Height; y++) + { + bitmap[x, y] = true; + } + } + + for (int i = 0; i < rounds; i++) + { + smoothFunction.FloodEffect(map, bitmap, 1.0); + } + } + + private void FillMap(ITerrainChannel map, double val) + { + for (int x = 0; x < map.Width; x++) + for (int y = 0; y < map.Height; y++) + map[x, y] = val; + } + + private void BuildTiles(ITerrainChannel map, double height) + { + int channelWidth = (int) Math.Floor((map.Width / num_w) * 0.8); + int channelHeight = (int) Math.Floor((map.Height / num_h) * 0.8); + int channelXOffset = (map.Width / num_w) - channelWidth; + int channelYOffset = (map.Height / num_h) - channelHeight; + + for (int x = 0; x < num_w; x++) + { + for (int y = 0; y < num_h; y++) + { + int xoff = ((channelXOffset + channelWidth) * x) + (channelXOffset / 2); + int yoff = ((channelYOffset + channelHeight) * y) + (channelYOffset / 2); + + Boolean[,] bitmap = new bool[map.Width,map.Height]; + + for (int dx = 0; dx < channelWidth; dx++) + { + for (int dy = 0; dy < channelHeight; dy++) + { + bitmap[dx + xoff, dy + yoff] = true; + } + } + + raiseFunction.FloodEffect(map, bitmap, height); + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs new file mode 100644 index 0000000..cb8112c --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs @@ -0,0 +1,125 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; + +namespace OpenSim.Region.CoreModules.World.Terrain.Effects +{ + internal class CookieCutter : ITerrainEffect + { + #region ITerrainEffect Members + + public void RunEffect(ITerrainChannel map) + { + ITerrainPaintableEffect eroder = new WeatherSphere(); + + bool[,] cliffMask = new bool[map.Width,map.Height]; + bool[,] channelMask = new bool[map.Width,map.Height]; + bool[,] smoothMask = new bool[map.Width,map.Height]; + bool[,] allowMask = new bool[map.Width,map.Height]; + + Console.WriteLine("S1"); + + // Step one, generate rough mask + int x, y; + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + Console.Write("."); + smoothMask[x, y] = true; + allowMask[x,y] = true; + + // Start underwater + map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 5; + // Add a little height. (terrain should now be above water, mostly.) + map[x, y] += 20; + + const int channelsX = 4; + int channelWidth = (map.Width / channelsX / 4); + const int channelsY = 4; + int channelHeight = (map.Height / channelsY / 4); + + SetLowerChannel(map, cliffMask, channelMask, x, y, channelsX, channelWidth, map.Width, x); + SetLowerChannel(map, cliffMask, channelMask, x, y, channelsY, channelHeight, map.Height, y); + } + } + + Console.WriteLine("S2"); + //smooth.FloodEffect(map, smoothMask, 4.0); + + Console.WriteLine("S3"); + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + if (cliffMask[x, y]) + eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1); + } + } + + for (x = 0; x < map.Width; x += 2) + { + for (y = 0; y < map.Height; y += 2) + { + if (map[x, y] < 0.1) + map[x, y] = 0.1; + if (map[x, y] > 256) + map[x, y] = 256; + } + } + //smooth.FloodEffect(map, smoothMask, 4.0); + } + + #endregion + + private static void SetLowerChannel(ITerrainChannel map, bool[,] cliffMask, bool[,] channelMask, int x, int y, int numChannels, int channelWidth, + int mapSize, int rp) + { + for (int i = 0; i < numChannels; i++) + { + double distanceToLine = Math.Abs(rp - ((mapSize / numChannels) * i)); + + if (distanceToLine < channelWidth) + { + if (channelMask[x, y]) + return; + + // Remove channels + map[x, y] -= 10; + channelMask[x, y] = true; + } + if (distanceToLine < 1) + { + cliffMask[x, y] = true; + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs new file mode 100644 index 0000000..da6ee12 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.Effects +{ + internal class DefaultTerrainGenerator : ITerrainEffect + { + #region ITerrainEffect Members + + public void RunEffect(ITerrainChannel map) + { + int x, y; + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10; + double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01; + if (map[x, y] < spherFac) + { + map[x, y] = spherFac; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs new file mode 100644 index 0000000..4f395b5 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/BMP.cs @@ -0,0 +1,76 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + /// + /// A generic windows bitmap loader. + /// Should be capable of handling 24-bit RGB images. + /// + /// Uses the System.Drawing filesystem loader. + /// + internal class BMP : GenericSystemDrawing + { + /// + /// Exports a file to a image on the disk using a System.Drawing exporter. + /// + /// The target filename + /// The terrain channel being saved + public override void SaveFile(string filename, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(filename, ImageFormat.Bmp); + } + + /// + /// Exports a stream using a System.Drawing exporter. + /// + /// The target stream + /// The terrain channel being saved + public override void SaveStream(Stream stream, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(stream, ImageFormat.Png); + } + + /// + /// The human readable version of the file format(s) this loader handles + /// + /// + public override string ToString() + { + return "BMP"; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs new file mode 100644 index 0000000..cff82d1 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GIF.cs @@ -0,0 +1,61 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + internal class GIF : GenericSystemDrawing + { + public override void SaveFile(string filename, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(filename, ImageFormat.Gif); + } + + /// + /// Exports a stream using a System.Drawing exporter. + /// + /// The target stream + /// The terrain channel being saved + public override void SaveStream(Stream stream, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(stream, ImageFormat.Gif); + } + + public override string ToString() + { + return "GIF"; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs new file mode 100644 index 0000000..477c73c --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs @@ -0,0 +1,195 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + /// + /// A virtual class designed to have methods overloaded, + /// this class provides an interface for a generic image + /// saving and loading mechanism, but does not specify the + /// format. It should not be insubstantiated directly. + /// + public class GenericSystemDrawing : ITerrainLoader + { + #region ITerrainLoader Members + + public string FileExtension + { + get { return ".gsd"; } + } + + /// + /// Loads a file from a specified filename on the disk, + /// parses the image using the System.Drawing parsers + /// then returns a terrain channel. Values are + /// returned based on HSL brightness between 0m and 128m + /// + /// The target image to load + /// A terrain channel generated from the image. + public virtual ITerrainChannel LoadFile(string filename) + { + return LoadBitmap(new Bitmap(filename)); + } + + public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) + { + throw new NotImplementedException(); + } + + public virtual ITerrainChannel LoadStream(Stream stream) + { + return LoadBitmap(new Bitmap(stream)); + } + + protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap) + { + ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height); + + int x; + for (x = 0; x < bitmap.Width; x++) + { + int y; + for (y = 0; y < bitmap.Height; y++) + { + retval[x, y] = bitmap.GetPixel(x, bitmap.Height - y - 1).GetBrightness() * 128; + } + } + + return retval; + } + + /// + /// Exports a file to a image on the disk using a System.Drawing exporter. + /// + /// The target filename + /// The terrain channel being saved + public virtual void SaveFile(string filename, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(filename, ImageFormat.Png); + } + + /// + /// Exports a stream using a System.Drawing exporter. + /// + /// The target stream + /// The terrain channel being saved + public virtual void SaveStream(Stream stream, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(stream, ImageFormat.Png); + } + + #endregion + + public override string ToString() + { + return "SYS.DRAWING"; + } + + /// + /// Protected method, generates a grayscale bitmap + /// image from a specified terrain channel. + /// + /// The terrain channel to export to bitmap + /// A System.Drawing.Bitmap containing a grayscale image + protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) + { + Bitmap bmp = new Bitmap(map.Width, map.Height); + + const int pallete = 256; + + Color[] grays = new Color[pallete]; + for (int i = 0; i < grays.Length; i++) + { + grays[i] = Color.FromArgb(i, i, i); + } + + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + // 512 is the largest possible height before colours clamp + int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 128.0), 0.0) * (pallete - 1)); + + // Handle error conditions + if (colorindex > pallete - 1 || colorindex < 0) + bmp.SetPixel(x, map.Height - y - 1, Color.Red); + else + bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]); + } + } + return bmp; + } + + /// + /// Protected method, generates a coloured bitmap + /// image from a specified terrain channel. + /// + /// The terrain channel to export to bitmap + /// A System.Drawing.Bitmap containing a coloured image + protected static Bitmap CreateBitmapFromMap(ITerrainChannel map) + { + Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); + + int pallete = gradientmapLd.Height; + + Bitmap bmp = new Bitmap(map.Width, map.Height); + Color[] colours = new Color[pallete]; + + for (int i = 0; i < pallete; i++) + { + colours[i] = gradientmapLd.GetPixel(0, i); + } + + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + // 512 is the largest possible height before colours clamp + int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1)); + + // Handle error conditions + if (colorindex > pallete - 1 || colorindex < 0) + bmp.SetPixel(x, map.Height - y - 1, Color.Red); + else + bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); + } + } + return bmp; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs new file mode 100644 index 0000000..f8e31f8 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/JPEG.cs @@ -0,0 +1,112 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + public class JPEG : ITerrainLoader + { + #region ITerrainLoader Members + + public string FileExtension + { + get { return ".jpg"; } + } + + public ITerrainChannel LoadFile(string filename) + { + throw new NotImplementedException(); + } + + public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) + { + throw new NotImplementedException(); + } + + public ITerrainChannel LoadStream(Stream stream) + { + throw new NotImplementedException(); + } + + public void SaveFile(string filename, ITerrainChannel map) + { + Bitmap colours = CreateBitmapFromMap(map); + + colours.Save(filename, ImageFormat.Jpeg); + } + + /// + /// Exports a stream using a System.Drawing exporter. + /// + /// The target stream + /// The terrain channel being saved + public void SaveStream(Stream stream, ITerrainChannel map) + { + Bitmap colours = CreateBitmapFromMap(map); + + colours.Save(stream, ImageFormat.Jpeg); + } + + #endregion + + public override string ToString() + { + return "JPEG"; + } + + private static Bitmap CreateBitmapFromMap(ITerrainChannel map) + { + Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); + + int pallete = gradientmapLd.Height; + + Bitmap bmp = new Bitmap(map.Width, map.Height); + Color[] colours = new Color[pallete]; + + for (int i = 0; i < pallete; i++) + { + colours[i] = gradientmapLd.GetPixel(0, i); + } + + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + // 512 is the largest possible height before colours clamp + int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1)); + bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); + } + } + return bmp; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs new file mode 100644 index 0000000..a86ae00 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs @@ -0,0 +1,250 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + public class LLRAW : ITerrainLoader + { + public struct HeightmapLookupValue : IComparable + { + public int Index; + public double Value; + + public HeightmapLookupValue(int index, double value) + { + Index = index; + Value = value; + } + + public int CompareTo(HeightmapLookupValue val) + { + return Value.CompareTo(val.Value); + } + } + + /// Lookup table to speed up terrain exports + HeightmapLookupValue[] LookupHeightTable; + + public LLRAW() + { + LookupHeightTable = new HeightmapLookupValue[256 * 256]; + + for (int i = 0; i < 256; i++) + { + for (int j = 0; j < 256; j++) + { + LookupHeightTable[i + (j * 256)] = new HeightmapLookupValue(i + (j * 256), ((double)i * ((double)j / 128.0d))); + } + } + Array.Sort(LookupHeightTable); + } + + #region ITerrainLoader Members + + public ITerrainChannel LoadFile(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + ITerrainChannel retval = LoadStream(s); + + s.Close(); + + return retval; + } + + public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight) + { + TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight); + + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + + int currFileYOffset = fileHeight - 1; + + // if our region isn't on the first Y section of the areas to be landscaped, then + // advance to our section of the file + while (currFileYOffset > offsetY) + { + // read a whole strip of regions + int heightsToRead = sectionHeight * (fileWidth * sectionWidth); + bs.ReadBytes(heightsToRead * 13); // because there are 13 fun channels + currFileYOffset--; + } + + // got to the Y start offset within the file of our region + // so read the file bits associated with our region + int y; + // for each Y within our Y offset + for (y = sectionHeight - 1; y >= 0; y--) + { + int currFileXOffset = 0; + + // if our region isn't the first X section of the areas to be landscaped, then + // advance the stream to the X start pos of our section in the file + // i.e. eat X upto where we start + while (currFileXOffset < offsetX) + { + bs.ReadBytes(sectionWidth * 13); + currFileXOffset++; + } + + // got to our X offset, so write our regions X line + int x; + for (x = 0; x < sectionWidth; x++) + { + // Read a strip and continue + retval[x, y] = bs.ReadByte() * (bs.ReadByte() / 128.0); + bs.ReadBytes(11); + } + // record that we wrote it + currFileXOffset++; + + // if our region isn't the last X section of the areas to be landscaped, then + // advance the stream to the end of this Y column + while (currFileXOffset < fileWidth) + { + // eat the next regions x line + bs.ReadBytes(sectionWidth * 13); //The 13 channels again + currFileXOffset++; + } + } + + bs.Close(); + s.Close(); + + return retval; + } + + public ITerrainChannel LoadStream(Stream s) + { + TerrainChannel retval = new TerrainChannel(); + + BinaryReader bs = new BinaryReader(s); + int y; + for (y = 0; y < retval.Height; y++) + { + int x; + for (x = 0; x < retval.Width; x++) + { + retval[x, (retval.Height - 1) - y] = bs.ReadByte() * (bs.ReadByte() / 128.0); + bs.ReadBytes(11); // Advance the stream to next bytes. + } + } + + bs.Close(); + + return retval; + } + + public void SaveFile(string filename, ITerrainChannel map) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); + SaveStream(s, map); + + s.Close(); + } + + public void SaveStream(Stream s, ITerrainChannel map) + { + BinaryWriter binStream = new BinaryWriter(s); + + // Output the calculated raw + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + double t = map[x, (map.Height - 1) - y]; + //if height is less than 0, set it to 0 as + //can't save -ve values in a LLRAW file + if (t < 0d) + { + t = 0d; + } + + int index = 0; + + // The lookup table is pre-sorted, so we either find an exact match or + // the next closest (smaller) match with a binary search + index = Array.BinarySearch(LookupHeightTable, new HeightmapLookupValue(0, t)); + if (index < 0) + index = ~index - 1; + + index = LookupHeightTable[index].Index; + + byte red = (byte) (index & 0xFF); + byte green = (byte) ((index >> 8) & 0xFF); + const byte blue = 20; + const byte alpha1 = 0; + const byte alpha2 = 0; + const byte alpha3 = 0; + const byte alpha4 = 0; + const byte alpha5 = 255; + const byte alpha6 = 255; + const byte alpha7 = 255; + const byte alpha8 = 255; + byte alpha9 = red; + byte alpha10 = green; + + binStream.Write(red); + binStream.Write(green); + binStream.Write(blue); + binStream.Write(alpha1); + binStream.Write(alpha2); + binStream.Write(alpha3); + binStream.Write(alpha4); + binStream.Write(alpha5); + binStream.Write(alpha6); + binStream.Write(alpha7); + binStream.Write(alpha8); + binStream.Write(alpha9); + binStream.Write(alpha10); + } + } + + binStream.Close(); + } + + public string FileExtension + { + get { return ".raw"; } + } + + #endregion + + public override string ToString() + { + return "LL/SL RAW"; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs new file mode 100644 index 0000000..0dea282 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/PNG.cs @@ -0,0 +1,61 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + internal class PNG : GenericSystemDrawing + { + public override void SaveFile(string filename, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(filename, ImageFormat.Png); + } + + /// + /// Exports a stream using a System.Drawing exporter. + /// + /// The target stream + /// The terrain channel being saved + public override void SaveStream(Stream stream, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(stream, ImageFormat.Png); + } + + public override string ToString() + { + return "PNG"; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs new file mode 100644 index 0000000..178104f --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/RAW32.cs @@ -0,0 +1,170 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.IO; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + public class RAW32 : ITerrainLoader + { + #region ITerrainLoader Members + + public string FileExtension + { + get { return ".r32"; } + } + + public ITerrainChannel LoadFile(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + ITerrainChannel retval = LoadStream(s); + + s.Close(); + + return retval; + } + + public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight) + { + TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight); + + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + + int currFileYOffset = 0; + + // if our region isn't on the first Y section of the areas to be landscaped, then + // advance to our section of the file + while (currFileYOffset < offsetY) + { + // read a whole strip of regions + int heightsToRead = sectionHeight * (fileWidth * sectionWidth); + bs.ReadBytes(heightsToRead * 4); // because the floats are 4 bytes in the file + currFileYOffset++; + } + + // got to the Y start offset within the file of our region + // so read the file bits associated with our region + int y; + // for each Y within our Y offset + for (y = 0; y < sectionHeight; y++) + { + int currFileXOffset = 0; + + // if our region isn't the first X section of the areas to be landscaped, then + // advance the stream to the X start pos of our section in the file + // i.e. eat X upto where we start + while (currFileXOffset < offsetX) + { + bs.ReadBytes(sectionWidth * 4); // 4 bytes = single + currFileXOffset++; + } + + // got to our X offset, so write our regions X line + int x; + for (x = 0; x < sectionWidth; x++) + { + // Read a strip and continue + retval[x, y] = bs.ReadSingle(); + } + // record that we wrote it + currFileXOffset++; + + // if our region isn't the last X section of the areas to be landscaped, then + // advance the stream to the end of this Y column + while (currFileXOffset < fileWidth) + { + // eat the next regions x line + bs.ReadBytes(sectionWidth * 4); // 4 bytes = single + currFileXOffset++; + } + } + + bs.Close(); + s.Close(); + + return retval; + } + + public ITerrainChannel LoadStream(Stream s) + { + TerrainChannel retval = new TerrainChannel(); + + BinaryReader bs = new BinaryReader(s); + int y; + for (y = 0; y < retval.Height; y++) + { + int x; + for (x = 0; x < retval.Width; x++) + { + retval[x, y] = bs.ReadSingle(); + } + } + + bs.Close(); + + return retval; + } + + public void SaveFile(string filename, ITerrainChannel map) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Create, FileAccess.Write); + SaveStream(s, map); + + s.Close(); + } + + public void SaveStream(Stream s, ITerrainChannel map) + { + BinaryWriter bs = new BinaryWriter(s); + + int y; + for (y = 0; y < map.Height; y++) + { + int x; + for (x = 0; x < map.Width; x++) + { + bs.Write((float) map[x, y]); + } + } + + bs.Close(); + } + + #endregion + + public override string ToString() + { + return "RAW32"; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs new file mode 100644 index 0000000..220431f --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/TIFF.cs @@ -0,0 +1,61 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + internal class TIFF : GenericSystemDrawing + { + public override void SaveFile(string filename, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(filename, ImageFormat.Tiff); + } + + /// + /// Exports a stream using a System.Drawing exporter. + /// + /// The target stream + /// The terrain channel being saved + public override void SaveStream(Stream stream, ITerrainChannel map) + { + Bitmap colours = CreateGrayscaleBitmapFromMap(map); + + colours.Save(stream, ImageFormat.Tiff); + } + + public override string ToString() + { + return "TIFF"; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs new file mode 100644 index 0000000..426708d --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs @@ -0,0 +1,142 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Text; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders +{ + /// + /// Terragen File Format Loader + /// Built from specification at + /// http://www.planetside.co.uk/terragen/dev/tgterrain.html + /// + internal class Terragen : ITerrainLoader + { + #region ITerrainLoader Members + + public ITerrainChannel LoadFile(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + ITerrainChannel retval = LoadStream(s); + + s.Close(); + + return retval; + } + + public ITerrainChannel LoadStream(Stream s) + { + TerrainChannel retval = new TerrainChannel(); + + BinaryReader bs = new BinaryReader(s); + + bool eof = false; + if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") + { + int w = 256; + int h = 256; + + // Terragen file + while (eof == false) + { + string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4)); + switch (tmp) + { + case "SIZE": + int sztmp = bs.ReadInt16() + 1; + w = sztmp; + h = sztmp; + bs.ReadInt16(); + break; + case "XPTS": + w = bs.ReadInt16(); + bs.ReadInt16(); + break; + case "YPTS": + h = bs.ReadInt16(); + bs.ReadInt16(); + break; + case "ALTW": + eof = true; + Int16 heightScale = bs.ReadInt16(); + Int16 baseHeight = bs.ReadInt16(); + retval = new TerrainChannel(w, h); + int x; + for (x = 0; x < w; x++) + { + int y; + for (y = 0; y < h; y++) + { + retval[x, y] = baseHeight + bs.ReadInt16() * (double) heightScale / 65536.0; + } + } + break; + default: + bs.ReadInt32(); + break; + } + } + } + + bs.Close(); + + return retval; + } + + public void SaveFile(string filename, ITerrainChannel map) + { + throw new NotImplementedException(); + } + + public void SaveStream(Stream stream, ITerrainChannel map) + { + throw new NotImplementedException(); + } + + public string FileExtension + { + get { return ".ter"; } + } + + public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) + { + throw new NotImplementedException(); + } + + #endregion + + public override string ToString() + { + return "Terragen"; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs new file mode 100644 index 0000000..fe79c0b --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes +{ + public class FlattenArea : ITerrainFloodEffect + { + #region ITerrainFloodEffect Members + + public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) + { + double sum = 0.0; + double steps = 0.0; + + int x, y; + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + if (fillArea[x, y]) + { + sum += map[x, y]; + steps += 1.0; + } + } + } + + double avg = sum / steps; + + double str = 0.1 * strength; // == 0.2 in the default client + + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + if (fillArea[x, y]) + map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs new file mode 100644 index 0000000..5c0aace --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes +{ + public class LowerArea : ITerrainFloodEffect + { + #region ITerrainFloodEffect Members + + public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) + { + int x; + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (fillArea[x, y]) + { + map[x, y] -= strength; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs new file mode 100644 index 0000000..02f2b53 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs @@ -0,0 +1,58 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes +{ + public class NoiseArea : ITerrainFloodEffect + { + #region ITerrainFloodEffect Members + + public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) + { + int x; + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (fillArea[x, y]) + { + double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0); + + map[x, y] += noise * strength; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs new file mode 100644 index 0000000..768b31f --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes +{ + public class RaiseArea : ITerrainFloodEffect + { + #region ITerrainFloodEffect Members + + public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) + { + int x; + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (fillArea[x, y]) + { + map[x, y] += strength; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs new file mode 100644 index 0000000..66b9055 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes +{ + public class RevertArea : ITerrainFloodEffect + { + private readonly ITerrainChannel m_revertmap; + + public RevertArea(ITerrainChannel revertmap) + { + m_revertmap = revertmap; + } + + #region ITerrainFloodEffect Members + + /// + /// reverts an area of the map to the heightfield stored in the revertmap + /// + /// the current heightmap + /// array indicating which sections of the map are to be reverted + /// unused + public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) + { + int x; + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (fillArea[x, y]) + { + map[x, y] = m_revertmap[x, y]; + } + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs new file mode 100644 index 0000000..a75dde1 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs @@ -0,0 +1,114 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes +{ + public class SmoothArea : ITerrainFloodEffect + { + #region ITerrainFloodEffect Members + + public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) + { + double area = strength; + double step = strength / 4.0; + + double[,] manipulate = new double[map.Width,map.Height]; + int x, y; + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + if (!fillArea[x, y]) + continue; + + double average = 0.0; + int avgsteps = 0; + + double n; + for (n = 0.0 - area; n < area; n += step) + { + double l; + for (l = 0.0 - area; l < area; l += step) + { + avgsteps++; + average += GetBilinearInterpolate(x + n, y + l, map); + } + } + + manipulate[x, y] = average / avgsteps; + } + } + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + if (!fillArea[x, y]) + continue; + + map[x, y] = manipulate[x, y]; + } + } + } + + #endregion + + private static double GetBilinearInterpolate(double x, double y, ITerrainChannel map) + { + int w = map.Width; + int h = map.Height; + + if (x > w - 2.0) + x = w - 2.0; + if (y > h - 2.0) + y = h - 2.0; + if (x < 0.0) + x = 0.0; + if (y < 0.0) + y = 0.0; + + const int stepSize = 1; + double h00 = map[(int) x, (int) y]; + double h10 = map[(int) x + stepSize, (int) y]; + double h01 = map[(int) x, (int) y + stepSize]; + double h11 = map[(int) x + stepSize, (int) y + stepSize]; + double h1 = h00; + double h2 = h10; + double h3 = h01; + double h4 = h11; + double a00 = h1; + double a10 = h2 - h1; + double a01 = h3 - h1; + double a11 = h1 - h2 - h3 + h4; + double partialx = x - (int) x; + double partialz = y - (int) y; + double hi = a00 + (a10 * partialx) + (a01 * partialz) + (a11 * partialx * partialz); + return hi; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainEffect.cs new file mode 100644 index 0000000..40b9f5a --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainEffect.cs @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public interface ITerrainEffect + { + void RunEffect(ITerrainChannel map); + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs new file mode 100644 index 0000000..eee7a83 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public interface ITerrainFloodEffect + { + void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength); + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs new file mode 100644 index 0000000..c62b897 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainLoader.cs @@ -0,0 +1,42 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.IO; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public interface ITerrainLoader + { + string FileExtension { get; } + ITerrainChannel LoadFile(string filename); + ITerrainChannel LoadFile(string filename, int fileStartX, int fileStartY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight); + ITerrainChannel LoadStream(Stream stream); + void SaveFile(string filename, ITerrainChannel map); + void SaveStream(Stream stream, ITerrainChannel map); + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModule.cs new file mode 100644 index 0000000..8c5d1d9 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModule.cs @@ -0,0 +1,61 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +using System.IO; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public interface ITerrainModule + { + void LoadFromFile(string filename); + void SaveToFile(string filename); + void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action, UUID agentId); + + /// + /// Load a terrain from a stream. + /// + /// + /// Only required here to identify the image type. Not otherwise used in the loading itself. + /// + /// + void LoadFromStream(string filename, Stream stream); + + /// + /// Save a terrain to a stream. + /// + /// + /// Only required here to identify the image type. Not otherwise used in the saving itself. + /// + /// + void SaveToStream(string filename, Stream stream); + + void InstallPlugin(string name, ITerrainEffect plug); + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs new file mode 100644 index 0000000..15d9f6e --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public interface ITerrainPaintableEffect + { + void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z, double strength, double duration); + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs new file mode 100644 index 0000000..6ce6994 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs @@ -0,0 +1,318 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + /// + /// Hydraulic Erosion Brush + /// + public class ErodeSphere : ITerrainPaintableEffect + { + private const double rainHeight = 0.2; + private const int rounds = 10; + private const NeighbourSystem type = NeighbourSystem.Moore; + private const double waterSaturation = 0.30; + + #region Supporting Functions + + private static int[] Neighbours(NeighbourSystem neighbourType, int index) + { + int[] coord = new int[2]; + + index++; + + switch (neighbourType) + { + case NeighbourSystem.Moore: + switch (index) + { + case 1: + coord[0] = -1; + coord[1] = -1; + break; + + case 2: + coord[0] = -0; + coord[1] = -1; + break; + + case 3: + coord[0] = +1; + coord[1] = -1; + break; + + case 4: + coord[0] = -1; + coord[1] = -0; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + case 6: + coord[0] = +1; + coord[1] = -0; + break; + + case 7: + coord[0] = -1; + coord[1] = +1; + break; + + case 8: + coord[0] = -0; + coord[1] = +1; + break; + + case 9: + coord[0] = +1; + coord[1] = +1; + break; + + default: + break; + } + break; + + case NeighbourSystem.VonNeumann: + switch (index) + { + case 1: + coord[0] = 0; + coord[1] = -1; + break; + + case 2: + coord[0] = -1; + coord[1] = 0; + break; + + case 3: + coord[0] = +1; + coord[1] = 0; + break; + + case 4: + coord[0] = 0; + coord[1] = +1; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + default: + break; + } + break; + } + + return coord; + } + + private enum NeighbourSystem + { + Moore, + VonNeumann + } ; + + #endregion + + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + strength = TerrainUtil.MetersToSphericalStrength(strength); + + int x, y; + // Using one 'rain' round for this, so skipping a useless loop + // Will need to adapt back in for the Flood brush + + ITerrainChannel water = new TerrainChannel(map.Width, map.Height); + ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height); + + // Fill with rain + for (x = 0; x < water.Width; x++) + for (y = 0; y < water.Height; y++) + water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration); + + for (int i = 0; i < rounds; i++) + { + // Erode underlying terrain + for (x = 0; x < water.Width; x++) + { + for (y = 0; y < water.Height; y++) + { + if (mask[x,y]) + { + const double solConst = (1.0 / rounds); + double sedDelta = water[x, y] * solConst; + map[x, y] -= sedDelta; + sediment[x, y] += sedDelta; + } + } + } + + // Move water + for (x = 0; x < water.Width; x++) + { + for (y = 0; y < water.Height; y++) + { + if (water[x, y] <= 0) + continue; + + // Step 1. Calculate average of neighbours + + int neighbours = 0; + double altitudeTotal = 0.0; + double altitudeMe = map[x, y] + water[x, y]; + + const int NEIGHBOUR_ME = 4; + const int NEIGHBOUR_MAX = 9; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + + coords[0] += x; + coords[1] += y; + + if (coords[0] > map.Width - 1) + continue; + if (coords[1] > map.Height - 1) + continue; + if (coords[0] < 0) + continue; + if (coords[1] < 0) + continue; + + // Calculate total height of this neighbour + double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]]; + + // If it's greater than me... + if (altitudeNeighbour - altitudeMe < 0) + { + // Add it to our calculations + neighbours++; + altitudeTotal += altitudeNeighbour; + } + } + } + + if (neighbours == 0) + continue; + + double altitudeAvg = altitudeTotal / neighbours; + + // Step 2. Allocate water to neighbours. + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + + coords[0] += x; + coords[1] += y; + + if (coords[0] > map.Width - 1) + continue; + if (coords[1] > map.Height - 1) + continue; + if (coords[0] < 0) + continue; + if (coords[1] < 0) + continue; + + // Skip if we dont have water to begin with. + if (water[x, y] < 0) + continue; + + // Calculate our delta average + double altitudeDelta = altitudeMe - altitudeAvg; + + if (altitudeDelta < 0) + continue; + + // Calculate how much water we can move + double waterMin = Math.Min(water[x, y], altitudeDelta); + double waterDelta = waterMin * ((water[coords[0], coords[1]] + map[coords[0], coords[1]]) + / altitudeTotal); + + double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]); + + if (sedimentDelta > 0) + { + sediment[x, y] -= sedimentDelta; + sediment[coords[0], coords[1]] += sedimentDelta; + } + } + } + } + } + + // Evaporate + + for (x = 0; x < water.Width; x++) + { + for (y = 0; y < water.Height; y++) + { + water[x, y] *= 1.0 - (rainHeight / rounds); + + double waterCapacity = waterSaturation * water[x, y]; + + double sedimentDeposit = sediment[x, y] - waterCapacity; + if (sedimentDeposit > 0) + { + if (mask[x,y]) + { + sediment[x, y] -= sedimentDeposit; + map[x, y] += sedimentDeposit; + } + } + } + } + } + + // Deposit any remainder (should be minimal) + for (x = 0; x < water.Width; x++) + for (y = 0; y < water.Height; y++) + if (mask[x,y] && sediment[x, y] > 0) + map[x, y] += sediment[x, y]; + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs new file mode 100644 index 0000000..928a595 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs @@ -0,0 +1,101 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + public class FlattenSphere : ITerrainPaintableEffect + { + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + strength = TerrainUtil.MetersToSphericalStrength(strength); + + int x, y; + + if (rz < 0) { + double sum = 0.0; + double step2 = 0.0; + duration = 0.009; //MCP Should be read from ini file + + + // compute delta map + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); + + if (z > 0) // add in non-zero amount + { + sum += map[x, y] * z; + step2 += z; + } + } + } + rz = sum / step2; + } + + + // blend in map + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + if (!mask[x,y]) + continue; + + double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * duration; + + if (z > 0) // add in non-zero amount + { + if (z > 1.0) + z = 1.0; + + map[x, y] = (map[x, y] * (1.0 - z)) + (rz * z); + } + + double delta = rz - map[x, y]; + if (Math.Abs(delta) > 0.1) + delta *= 0.25; + + if (delta != 0) // add in non-zero amount + { + map[x, y] += delta; + } + + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs new file mode 100644 index 0000000..8c40088 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs @@ -0,0 +1,84 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + public class LowerSphere : ITerrainPaintableEffect + { + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + int s = (int) (Math.Pow(2, strength) + 0.5); + + int x; + int xFrom = (int)(rx-s+0.5); + int xTo = (int)(rx+s+0.5) + 1; + int yFrom = (int)(ry-s+0.5); + int yTo = (int)(ry+s+0.5) + 1; + + if (xFrom < 0) + xFrom = 0; + + if (yFrom < 0) + yFrom = 0; + + if (xTo > map.Width) + xTo = map.Width; + + if (yTo > map.Width) + yTo = map.Width; + + for (x = xFrom; x < xTo; x++) + { + int y; + for (y = yFrom; y < yTo; y++) + { + if (!mask[x,y]) + continue; + + // Calculate a cos-sphere and add it to the heighmap + double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry))); + double z = Math.Cos(r * Math.PI / (s * 2)); + if (z > 0.0) + { + double newz = map[x, y] - z * duration; + if (newz < 0.0) + map[x, y] = 0.0; + else + map[x, y] = newz; + } + } + } + + } + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs new file mode 100644 index 0000000..95a8c33 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + public class NoiseSphere : ITerrainPaintableEffect + { + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + strength = TerrainUtil.MetersToSphericalStrength(strength); + + int x; + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (!mask[x,y]) + continue; + + // Calculate a sphere and add it to the heighmap + double z = strength; + z *= z; + z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry)); + + double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0); + + if (z > 0.0) + map[x, y] += noise * z * duration; + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs new file mode 100644 index 0000000..1a2528a --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs @@ -0,0 +1,223 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + /// + /// Speed-Optimised Hybrid Erosion Brush + /// + /// As per Jacob Olsen's Paper + /// http://www.oddlabs.com/download/terrain_generation.pdf + /// + public class OlsenSphere : ITerrainPaintableEffect + { + private const double nConst = 1024.0; + private const NeighbourSystem type = NeighbourSystem.Moore; + + #region Supporting Functions + + private static int[] Neighbours(NeighbourSystem neighbourType, int index) + { + int[] coord = new int[2]; + + index++; + + switch (neighbourType) + { + case NeighbourSystem.Moore: + switch (index) + { + case 1: + coord[0] = -1; + coord[1] = -1; + break; + + case 2: + coord[0] = -0; + coord[1] = -1; + break; + + case 3: + coord[0] = +1; + coord[1] = -1; + break; + + case 4: + coord[0] = -1; + coord[1] = -0; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + case 6: + coord[0] = +1; + coord[1] = -0; + break; + + case 7: + coord[0] = -1; + coord[1] = +1; + break; + + case 8: + coord[0] = -0; + coord[1] = +1; + break; + + case 9: + coord[0] = +1; + coord[1] = +1; + break; + + default: + break; + } + break; + + case NeighbourSystem.VonNeumann: + switch (index) + { + case 1: + coord[0] = 0; + coord[1] = -1; + break; + + case 2: + coord[0] = -1; + coord[1] = 0; + break; + + case 3: + coord[0] = +1; + coord[1] = 0; + break; + + case 4: + coord[0] = 0; + coord[1] = +1; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + default: + break; + } + break; + } + + return coord; + } + + private enum NeighbourSystem + { + Moore, + VonNeumann + } ; + + #endregion + + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + strength = TerrainUtil.MetersToSphericalStrength(strength); + + int x; + + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (!mask[x,y]) + continue; + + double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); + + if (z > 0) // add in non-zero amount + { + const int NEIGHBOUR_ME = 4; + const int NEIGHBOUR_MAX = 9; + + double max = Double.MinValue; + int loc = 0; + + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + + coords[0] += x; + coords[1] += y; + + if (coords[0] > map.Width - 1) + continue; + if (coords[1] > map.Height - 1) + continue; + if (coords[0] < 0) + continue; + if (coords[1] < 0) + continue; + + double cellmax = map[x, y] - map[coords[0], coords[1]]; + if (cellmax > max) + { + max = cellmax; + loc = j; + } + } + } + + double T = nConst / ((map.Width + map.Height) / 2.0); + // Apply results + if (0 < max && max <= T) + { + int[] maxCoords = Neighbours(type, loc); + double heightDelta = 0.5 * max * z * duration; + map[x, y] -= heightDelta; + map[x + maxCoords[0], y + maxCoords[1]] += heightDelta; + } + } + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs new file mode 100644 index 0000000..c53bb7d --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs @@ -0,0 +1,80 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + public class RaiseSphere : ITerrainPaintableEffect + { + #region ITerrainPaintableEffect Members + + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + int s = (int) (Math.Pow(2, strength) + 0.5); + + int x; + int xFrom = (int)(rx-s+0.5); + int xTo = (int)(rx+s+0.5) + 1; + int yFrom = (int)(ry-s+0.5); + int yTo = (int)(ry+s+0.5) + 1; + + if (xFrom < 0) + xFrom = 0; + + if (yFrom < 0) + yFrom = 0; + + if (xTo > map.Width) + xTo = map.Width; + + if (yTo > map.Width) + yTo = map.Width; + + for (x = xFrom; x < xTo; x++) + { + int y; + for (y = yFrom; y < yTo; y++) + { + if (!mask[x,y]) + continue; + + // Calculate a cos-sphere and add it to the heighmap + double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry))); + double z = Math.Cos(r * Math.PI / (s * 2)); + if (z > 0.0) + map[x, y] += z * duration; + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs new file mode 100644 index 0000000..4ed8a13 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs @@ -0,0 +1,80 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + public class RevertSphere : ITerrainPaintableEffect + { + private readonly ITerrainChannel m_revertmap; + + public RevertSphere(ITerrainChannel revertmap) + { + m_revertmap = revertmap; + } + + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + strength = TerrainUtil.MetersToSphericalStrength(strength); + duration = 0.03; //MCP Should be read from ini file + + if (duration > 1.0) + duration = 1.0; + if (duration < 0) + return; + + int x; + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (!mask[x,y]) + continue; + + // Calculate a sphere and add it to the heighmap + double z = strength; + z *= z; + z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry)); + + if (z > 0.0) + { + z *= duration; + map[x, y] = (map[x, y] * (1.0 - z)) + (m_revertmap[x, y] * z); + } + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs new file mode 100644 index 0000000..6636d8f --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs @@ -0,0 +1,100 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + public class SmoothSphere : ITerrainPaintableEffect + { + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + strength = TerrainUtil.MetersToSphericalStrength(strength); + + int x, y; + double[,] tweak = new double[map.Width,map.Height]; + + double area = strength; + double step = strength / 4.0; + duration = 0.03; //MCP Should be read from ini file + + + // compute delta map + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); + + if (z > 0) // add in non-zero amount + { + double average = 0.0; + int avgsteps = 0; + + double n; + for (n = 0.0 - area; n < area; n += step) + { + double l; + for (l = 0.0 - area; l < area; l += step) + { + avgsteps++; + average += TerrainUtil.GetBilinearInterpolate(x + n, y + l, map); + } + } + tweak[x, y] = average / avgsteps; + } + } + } + // blend in map + for (x = 0; x < map.Width; x++) + { + for (y = 0; y < map.Height; y++) + { + if (!mask[x,y]) + continue; + + double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); + + if (z > 0) // add in non-zero amount + { + double da = z; + double a = (map[x, y] - tweak[x, y]) * da; + double newz = map[x, y] - (a * duration); + + if (newz > 0.0) + map[x, y] = newz; + } + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs new file mode 100644 index 0000000..6b00cc8 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs @@ -0,0 +1,211 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes +{ + /// + /// Thermal Weathering Paint Brush + /// + public class WeatherSphere : ITerrainPaintableEffect + { + private const double talus = 0.2; + private const NeighbourSystem type = NeighbourSystem.Moore; + + #region Supporting Functions + + private static int[] Neighbours(NeighbourSystem neighbourType, int index) + { + int[] coord = new int[2]; + + index++; + + switch (neighbourType) + { + case NeighbourSystem.Moore: + switch (index) + { + case 1: + coord[0] = -1; + coord[1] = -1; + break; + + case 2: + coord[0] = -0; + coord[1] = -1; + break; + + case 3: + coord[0] = +1; + coord[1] = -1; + break; + + case 4: + coord[0] = -1; + coord[1] = -0; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + case 6: + coord[0] = +1; + coord[1] = -0; + break; + + case 7: + coord[0] = -1; + coord[1] = +1; + break; + + case 8: + coord[0] = -0; + coord[1] = +1; + break; + + case 9: + coord[0] = +1; + coord[1] = +1; + break; + + default: + break; + } + break; + + case NeighbourSystem.VonNeumann: + switch (index) + { + case 1: + coord[0] = 0; + coord[1] = -1; + break; + + case 2: + coord[0] = -1; + coord[1] = 0; + break; + + case 3: + coord[0] = +1; + coord[1] = 0; + break; + + case 4: + coord[0] = 0; + coord[1] = +1; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + default: + break; + } + break; + } + + return coord; + } + + private enum NeighbourSystem + { + Moore, + VonNeumann + } ; + + #endregion + + #region ITerrainPaintableEffect Members + + public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) + { + strength = TerrainUtil.MetersToSphericalStrength(strength); + + int x; + + for (x = 0; x < map.Width; x++) + { + int y; + for (y = 0; y < map.Height; y++) + { + if (!mask[x,y]) + continue; + + double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); + + if (z > 0) // add in non-zero amount + { + const int NEIGHBOUR_ME = 4; + const int NEIGHBOUR_MAX = 9; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + + coords[0] += x; + coords[1] += y; + + if (coords[0] > map.Width - 1) + continue; + if (coords[1] > map.Height - 1) + continue; + if (coords[0] < 0) + continue; + if (coords[1] < 0) + continue; + + double heightF = map[x, y]; + double target = map[coords[0], coords[1]]; + + if (target > heightF + talus) + { + double calc = duration * ((target - heightF) - talus) * z; + heightF += calc; + target -= calc; + } + + map[x, y] = heightF; + map[coords[0], coords[1]] = target; + } + } + } + } + } + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainException.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainException.cs new file mode 100644 index 0000000..ff9b8ec --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainException.cs @@ -0,0 +1,46 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public class TerrainException : Exception + { + public TerrainException() + { + } + + public TerrainException(string msg) : base(msg) + { + } + + public TerrainException(string msg, Exception e) : base(msg, e) + { + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs new file mode 100644 index 0000000..9de7338 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -0,0 +1,1001 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.Framework.InterfaceCommander; +using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; +using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; +using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; + +namespace OpenSim.Region.CoreModules.World.Terrain +{ + public class TerrainModule : IRegionModule, ICommandableModule, ITerrainModule + { + #region StandardTerrainEffects enum + + /// + /// A standard set of terrain brushes and effects recognised by viewers + /// + public enum StandardTerrainEffects : byte + { + Flatten = 0, + Raise = 1, + Lower = 2, + Smooth = 3, + Noise = 4, + Revert = 5, + + // Extended brushes + Erode = 255, + Weather = 254, + Olsen = 253 + } + + #endregion + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private readonly Commander m_commander = new Commander("terrain"); + + private readonly Dictionary m_floodeffects = + new Dictionary(); + + private readonly Dictionary m_loaders = new Dictionary(); + + private readonly Dictionary m_painteffects = + new Dictionary(); + + private ITerrainChannel m_channel; + private Dictionary m_plugineffects; + private ITerrainChannel m_revert; + private Scene m_scene; + private bool m_tainted; + + #region ICommandableModule Members + + public ICommander CommandInterface + { + get { return m_commander; } + } + + #endregion + + #region IRegionModule Members + + /// + /// Creates and initialises a terrain module for a region + /// + /// Region initialising + /// Config for the region + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + + // Install terrain module in the simulator + if (m_scene.Heightmap == null) + { + lock (m_scene) + { + m_channel = new TerrainChannel(); + m_scene.Heightmap = m_channel; + m_revert = new TerrainChannel(); + UpdateRevertMap(); + } + } + else + { + m_channel = m_scene.Heightmap; + m_revert = new TerrainChannel(); + UpdateRevertMap(); + } + + m_scene.RegisterModuleInterface(this); + m_scene.EventManager.OnNewClient += EventManager_OnNewClient; + m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; + m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; + } + + /// + /// Enables terrain module when called + /// + public void PostInitialise() + { + InstallDefaultEffects(); + InstallInterfaces(); + LoadPlugins(); + } + + public void Close() + { + } + + public string Name + { + get { return "TerrainModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region ITerrainModule Members + + /// + /// Loads a terrain file from disk and installs it in the scene. + /// + /// Filename to terrain file. Type is determined by extension. + public void LoadFromFile(string filename) + { + foreach (KeyValuePair loader in m_loaders) + { + if (filename.EndsWith(loader.Key)) + { + lock (m_scene) + { + try + { + ITerrainChannel channel = loader.Value.LoadFile(filename); + if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize) + { + // TerrainChannel expects a RegionSize x RegionSize map, currently + throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}", + Constants.RegionSize, Constants.RegionSize)); + } + m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); + m_scene.Heightmap = channel; + m_channel = channel; + UpdateRevertMap(); + } + catch (NotImplementedException) + { + m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + + " parser does not support file loading. (May be save only)"); + throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); + } + catch (FileNotFoundException) + { + m_log.Error( + "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); + throw new TerrainException( + String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); + } + catch (ArgumentException e) + { + m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); + throw new TerrainException( + String.Format("Unable to load heightmap: {0}", e.Message)); + } + } + CheckForTerrainUpdates(); + m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); + return; + } + } + + m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format."); + throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); + } + + /// + /// Saves the current heightmap to a specified file. + /// + /// The destination filename + public void SaveToFile(string filename) + { + try + { + foreach (KeyValuePair loader in m_loaders) + { + if (filename.EndsWith(loader.Key)) + { + loader.Value.SaveFile(filename, m_channel); + return; + } + } + } + catch (NotImplementedException) + { + m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); + throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); + } + } + + /// + /// Loads a terrain file from a stream and installs it in the scene. + /// + /// Filename to terrain file. Type is determined by extension. + /// + public void LoadFromStream(string filename, Stream stream) + { + foreach (KeyValuePair loader in m_loaders) + { + if (@filename.EndsWith(loader.Key)) + { + lock (m_scene) + { + try + { + ITerrainChannel channel = loader.Value.LoadStream(stream); + m_scene.Heightmap = channel; + m_channel = channel; + UpdateRevertMap(); + } + catch (NotImplementedException) + { + m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + + " parser does not support file loading. (May be save only)"); + throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); + } + } + + CheckForTerrainUpdates(); + m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); + return; + } + } + m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format."); + throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); + } + + /// + /// Modify Land + /// + /// Land-position (X,Y,0) + /// The size of the brush (0=small, 1=medium, 2=large) + /// 0=LAND_LEVEL, 1=LAND_RAISE, 2=LAND_LOWER, 3=LAND_SMOOTH, 4=LAND_NOISE, 5=LAND_REVERT + /// UUID of script-owner + public void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action, UUID agentId) + { + client_OnModifyTerrain(user, (float)pos.Z, (float)0.25, size, action, pos.Y, pos.X, pos.Y, pos.X, agentId); + } + + /// + /// Saves the current heightmap to a specified stream. + /// + /// The destination filename. Used here only to identify the image type + /// + public void SaveToStream(string filename, Stream stream) + { + try + { + foreach (KeyValuePair loader in m_loaders) + { + if (filename.EndsWith(loader.Key)) + { + loader.Value.SaveStream(stream, m_channel); + return; + } + } + } + catch (NotImplementedException) + { + m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); + throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); + } + } + + #region Plugin Loading Methods + + private void LoadPlugins() + { + m_plugineffects = new Dictionary(); + // Load the files in the Terrain/ dir + string[] files = Directory.GetFiles("Terrain"); + foreach (string file in files) + { + m_log.Info("Loading effects in " + file); + try + { + Assembly library = Assembly.LoadFrom(file); + foreach (Type pluginType in library.GetTypes()) + { + try + { + if (pluginType.IsAbstract || pluginType.IsNotPublic) + continue; + + string typeName = pluginType.Name; + + if (pluginType.GetInterface("ITerrainEffect", false) != null) + { + ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); + + InstallPlugin(typeName, terEffect); + } + else if (pluginType.GetInterface("ITerrainLoader", false) != null) + { + ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); + m_loaders[terLoader.FileExtension] = terLoader; + m_log.Info("L ... " + typeName); + } + } + catch (AmbiguousMatchException) + { + } + } + } + catch (BadImageFormatException) + { + } + } + } + + public void InstallPlugin(string pluginName, ITerrainEffect effect) + { + lock (m_plugineffects) + { + if (!m_plugineffects.ContainsKey(pluginName)) + { + m_plugineffects.Add(pluginName, effect); + m_log.Info("E ... " + pluginName); + } + else + { + m_plugineffects[pluginName] = effect; + m_log.Warn("E ... " + pluginName + " (Replaced)"); + } + } + } + + #endregion + + #endregion + + /// + /// Installs into terrain module the standard suite of brushes + /// + private void InstallDefaultEffects() + { + // Draggable Paint Brush Effects + m_painteffects[StandardTerrainEffects.Raise] = new RaiseSphere(); + m_painteffects[StandardTerrainEffects.Lower] = new LowerSphere(); + m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere(); + m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere(); + m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere(); + m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert); + m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere(); + m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere(); + m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere(); + + // Area of effect selection effects + m_floodeffects[StandardTerrainEffects.Raise] = new RaiseArea(); + m_floodeffects[StandardTerrainEffects.Lower] = new LowerArea(); + m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea(); + m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea(); + m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); + m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); + + // Filesystem load/save loaders + m_loaders[".r32"] = new RAW32(); + m_loaders[".f32"] = m_loaders[".r32"]; + m_loaders[".ter"] = new Terragen(); + m_loaders[".raw"] = new LLRAW(); + m_loaders[".jpg"] = new JPEG(); + m_loaders[".jpeg"] = m_loaders[".jpg"]; + m_loaders[".bmp"] = new BMP(); + m_loaders[".png"] = new PNG(); + m_loaders[".gif"] = new GIF(); + m_loaders[".tif"] = new TIFF(); + m_loaders[".tiff"] = m_loaders[".tif"]; + } + + /// + /// Saves the current state of the region into the revert map buffer. + /// + public void UpdateRevertMap() + { + int x; + for (x = 0; x < m_channel.Width; x++) + { + int y; + for (y = 0; y < m_channel.Height; y++) + { + m_revert[x, y] = m_channel[x, y]; + } + } + } + + /// + /// Loads a tile from a larger terrain file and installs it into the region. + /// + /// The terrain file to load + /// The width of the file in units + /// The height of the file in units + /// Where to begin our slice + /// Where to begin our slice + public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) + { + int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX; + int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY; + + if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) + { + // this region is included in the tile request + foreach (KeyValuePair loader in m_loaders) + { + if (filename.EndsWith(loader.Key)) + { + lock (m_scene) + { + ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, + fileWidth, fileHeight, + (int) Constants.RegionSize, + (int) Constants.RegionSize); + m_scene.Heightmap = channel; + m_channel = channel; + UpdateRevertMap(); + } + return; + } + } + } + } + + /// + /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections + /// + private void EventManager_OnTerrainTick() + { + if (m_tainted) + { + m_tainted = false; + m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); + m_scene.SaveTerrain(); + + // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. + //m_scene.CreateTerrainTexture(true); + } + } + + /// + /// Processes commandline input. Do not call directly. + /// + /// Commandline arguments + private void EventManager_OnPluginConsole(string[] args) + { + if (args[0] == "terrain") + { + if (args.Length == 1) + { + m_commander.ProcessConsoleCommand("help", new string[0]); + return; + } + + string[] tmpArgs = new string[args.Length - 2]; + int i; + for (i = 2; i < args.Length; i++) + tmpArgs[i - 2] = args[i]; + + m_commander.ProcessConsoleCommand(args[1], tmpArgs); + } + } + + /// + /// Installs terrain brush hook to IClientAPI + /// + /// + private void EventManager_OnNewClient(IClientAPI client) + { + client.OnModifyTerrain += client_OnModifyTerrain; + client.OnBakeTerrain += client_OnBakeTerrain; + } + + /// + /// Checks to see if the terrain has been modified since last check + /// but won't attempt to limit those changes to the limits specified in the estate settings + /// currently invoked by the command line operations in the region server only + /// + private void CheckForTerrainUpdates() + { + CheckForTerrainUpdates(false); + } + + /// + /// Checks to see if the terrain has been modified since last check. + /// If it has been modified, every all the terrain patches are sent to the client. + /// If the call is asked to respect the estate settings for terrain_raise_limit and + /// terrain_lower_limit, it will clamp terrain updates between these values + /// currently invoked by client_OnModifyTerrain only and not the Commander interfaces + /// should height map deltas be limited to the estate settings limits + /// + private void CheckForTerrainUpdates(bool respectEstateSettings) + { + bool shouldTaint = false; + float[] serialised = m_channel.GetFloatsSerialised(); + int x; + for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) + { + int y; + for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize) + { + if (m_channel.Tainted(x, y)) + { + // if we should respect the estate settings then + // fixup and height deltas that don't respect them + if (respectEstateSettings && LimitChannelChanges(x, y)) + { + // this has been vetoed, so update + // what we are going to send to the client + serialised = m_channel.GetFloatsSerialised(); + } + + SendToClients(serialised, x, y); + shouldTaint = true; + } + } + } + if (shouldTaint) + { + m_tainted = true; + } + } + + /// + /// Checks to see height deltas in the tainted terrain patch at xStart ,yStart + /// are all within the current estate limits + /// true if changes were limited, false otherwise + /// + private bool LimitChannelChanges(int xStart, int yStart) + { + bool changesLimited = false; + double minDelta = m_scene.RegionInfo.RegionSettings.TerrainLowerLimit; + double maxDelta = m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; + + // loop through the height map for this patch and compare it against + // the revert map + for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) + { + for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) + { + + double requestedHeight = m_channel[x, y]; + double bakedHeight = m_revert[x, y]; + double requestedDelta = requestedHeight - bakedHeight; + + if (requestedDelta > maxDelta) + { + m_channel[x, y] = bakedHeight + maxDelta; + changesLimited = true; + } + else if (requestedDelta < minDelta) + { + m_channel[x, y] = bakedHeight + minDelta; //as lower is a -ve delta + changesLimited = true; + } + } + } + + return changesLimited; + } + + /// + /// Sends a copy of the current terrain to the scenes clients + /// + /// A copy of the terrain as a 1D float array of size w*h + /// The patch corner to send + /// The patch corner to send + private void SendToClients(float[] serialised, int x, int y) + { + m_scene.ForEachClient( + delegate(IClientAPI controller) + { controller.SendLayerData( + x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised); + } + ); + } + + private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action, + float north, float west, float south, float east, UUID agentId) + { + bool god = m_scene.Permissions.IsGod(user); + bool allowed = false; + if (north == south && east == west) + { + if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) + { + bool[,] allowMask = new bool[m_channel.Width,m_channel.Height]; + allowMask.Initialize(); + int n = size + 1; + if (n > 2) + n = 4; + + int zx = (int) (west + 0.5); + int zy = (int) (north + 0.5); + + int dx; + for (dx=-n; dx<=n; dx++) + { + int dy; + for (dy=-n; dy<=n; dy++) + { + int x = zx + dx; + int y = zy + dy; + if (x>=0 && y>=0 && x west) + { + if (y < north && y > south) + { + if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) + { + fillArea[x, y] = true; + allowed = true; + } + } + } + } + } + + if (allowed) + { + m_floodeffects[(StandardTerrainEffects) action].FloodEffect( + m_channel, fillArea, size); + + CheckForTerrainUpdates(!god); //revert changes outside estate limits + } + } + else + { + m_log.Debug("Unknown terrain flood type " + action); + } + } + } + + private void client_OnBakeTerrain(IClientAPI remoteClient) + { + // Not a good permissions check (see client_OnModifyTerrain above), need to check the entire area. + // for now check a point in the centre of the region + + if (m_scene.Permissions.CanIssueEstateCommand(remoteClient.AgentId, true)) + { + InterfaceBakeTerrain(null); //bake terrain does not use the passed in parameter + } + } + + #region Console Commands + + private void InterfaceLoadFile(Object[] args) + { + LoadFromFile((string) args[0]); + CheckForTerrainUpdates(); + } + + private void InterfaceLoadTileFile(Object[] args) + { + LoadFromFile((string) args[0], + (int) args[1], + (int) args[2], + (int) args[3], + (int) args[4]); + CheckForTerrainUpdates(); + } + + private void InterfaceSaveFile(Object[] args) + { + SaveToFile((string) args[0]); + } + + private void InterfaceBakeTerrain(Object[] args) + { + UpdateRevertMap(); + } + + private void InterfaceRevertTerrain(Object[] args) + { + int x, y; + for (x = 0; x < m_channel.Width; x++) + for (y = 0; y < m_channel.Height; y++) + m_channel[x, y] = m_revert[x, y]; + + CheckForTerrainUpdates(); + } + + private void InterfaceFlipTerrain(Object[] args) + { + String direction = (String)args[0]; + + if (direction.ToLower().StartsWith("y")) + { + for (int x = 0; x < Constants.RegionSize; x++) + { + for (int y = 0; y < Constants.RegionSize / 2; y++) + { + double height = m_channel[x, y]; + double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y]; + m_channel[x, y] = flippedHeight; + m_channel[x, (int)Constants.RegionSize - 1 - y] = height; + + } + } + } + else if (direction.ToLower().StartsWith("x")) + { + for (int y = 0; y < Constants.RegionSize; y++) + { + for (int x = 0; x < Constants.RegionSize / 2; x++) + { + double height = m_channel[x, y]; + double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y]; + m_channel[x, y] = flippedHeight; + m_channel[(int)Constants.RegionSize - 1 - x, y] = height; + + } + } + } + else + { + m_log.Error("Unrecognised direction - need x or y"); + } + + + CheckForTerrainUpdates(); + } + + private void InterfaceElevateTerrain(Object[] args) + { + int x, y; + for (x = 0; x < m_channel.Width; x++) + for (y = 0; y < m_channel.Height; y++) + m_channel[x, y] += (double) args[0]; + CheckForTerrainUpdates(); + } + + private void InterfaceMultiplyTerrain(Object[] args) + { + int x, y; + for (x = 0; x < m_channel.Width; x++) + for (y = 0; y < m_channel.Height; y++) + m_channel[x, y] *= (double) args[0]; + CheckForTerrainUpdates(); + } + + private void InterfaceLowerTerrain(Object[] args) + { + int x, y; + for (x = 0; x < m_channel.Width; x++) + for (y = 0; y < m_channel.Height; y++) + m_channel[x, y] -= (double) args[0]; + CheckForTerrainUpdates(); + } + + private void InterfaceFillTerrain(Object[] args) + { + int x, y; + + for (x = 0; x < m_channel.Width; x++) + for (y = 0; y < m_channel.Height; y++) + m_channel[x, y] = (double) args[0]; + CheckForTerrainUpdates(); + } + + private void InterfaceShowDebugStats(Object[] args) + { + double max = Double.MinValue; + double min = double.MaxValue; + double sum = 0; + + int x; + for (x = 0; x < m_channel.Width; x++) + { + int y; + for (y = 0; y < m_channel.Height; y++) + { + sum += m_channel[x, y]; + if (max < m_channel[x, y]) + max = m_channel[x, y]; + if (min > m_channel[x, y]) + min = m_channel[x, y]; + } + } + + double avg = sum / (m_channel.Height * m_channel.Width); + + m_log.Info("Channel " + m_channel.Width + "x" + m_channel.Height); + m_log.Info("max/min/avg/sum: " + max + "/" + min + "/" + avg + "/" + sum); + } + + private void InterfaceEnableExperimentalBrushes(Object[] args) + { + if ((bool) args[0]) + { + m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); + m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); + m_painteffects[StandardTerrainEffects.Smooth] = new ErodeSphere(); + } + else + { + InstallDefaultEffects(); + } + } + + private void InterfaceRunPluginEffect(Object[] args) + { + if ((string) args[0] == "list") + { + m_log.Info("List of loaded plugins"); + foreach (KeyValuePair kvp in m_plugineffects) + { + m_log.Info(kvp.Key); + } + return; + } + if ((string) args[0] == "reload") + { + LoadPlugins(); + return; + } + if (m_plugineffects.ContainsKey((string) args[0])) + { + m_plugineffects[(string) args[0]].RunEffect(m_channel); + CheckForTerrainUpdates(); + } + else + { + m_log.Warn("No such plugin effect loaded."); + } + } + + private void InstallInterfaces() + { + // Load / Save + string supportedFileExtensions = ""; + foreach (KeyValuePair loader in m_loaders) + supportedFileExtensions += " " + loader.Key + " (" + loader.Value + ")"; + + Command loadFromFileCommand = + new Command("load", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadFile, "Loads a terrain from a specified file."); + loadFromFileCommand.AddArgument("filename", + "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + + supportedFileExtensions, "String"); + + Command saveToFileCommand = + new Command("save", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveFile, "Saves the current heightmap to a specified file."); + saveToFileCommand.AddArgument("filename", + "The destination filename for your heightmap, the file extension determines the format to save in. Supported extensions include: " + + supportedFileExtensions, "String"); + + Command loadFromTileCommand = + new Command("load-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadTileFile, "Loads a terrain from a section of a larger file."); + loadFromTileCommand.AddArgument("filename", + "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + + supportedFileExtensions, "String"); + loadFromTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer"); + loadFromTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer"); + loadFromTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file", + "Integer"); + loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file", + "Integer"); + + // Terrain adjustments + Command fillRegionCommand = + new Command("fill", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFillTerrain, "Fills the current heightmap with a specified value."); + fillRegionCommand.AddArgument("value", "The numeric value of the height you wish to set your region to.", + "Double"); + + Command elevateCommand = + new Command("elevate", CommandIntentions.COMMAND_HAZARDOUS, InterfaceElevateTerrain, "Raises the current heightmap by the specified amount."); + elevateCommand.AddArgument("amount", "The amount of height to add to the terrain in meters.", "Double"); + + Command lowerCommand = + new Command("lower", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLowerTerrain, "Lowers the current heightmap by the specified amount."); + lowerCommand.AddArgument("amount", "The amount of height to remove from the terrain in meters.", "Double"); + + Command multiplyCommand = + new Command("multiply", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified."); + multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); + + Command bakeRegionCommand = + new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); + Command revertRegionCommand = + new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); + + Command flipCommand = + new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis"); + flipCommand.AddArgument("direction", "[x|y] the direction to flip the terrain in", "String"); + + // Debug + Command showDebugStatsCommand = + new Command("stats", CommandIntentions.COMMAND_STATISTICAL, InterfaceShowDebugStats, + "Shows some information about the regions heightmap for debugging purposes."); + + Command experimentalBrushesCommand = + new Command("newbrushes", CommandIntentions.COMMAND_HAZARDOUS, InterfaceEnableExperimentalBrushes, + "Enables experimental brushes which replace the standard terrain brushes. WARNING: This is a debug setting and may be removed at any time."); + experimentalBrushesCommand.AddArgument("Enabled?", "true / false - Enable new brushes", "Boolean"); + + //Plugins + Command pluginRunCommand = + new Command("effect", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRunPluginEffect, "Runs a specified plugin effect"); + pluginRunCommand.AddArgument("name", "The plugin effect you wish to run, or 'list' to see all plugins", "String"); + + m_commander.RegisterCommand("load", loadFromFileCommand); + m_commander.RegisterCommand("load-tile", loadFromTileCommand); + m_commander.RegisterCommand("save", saveToFileCommand); + m_commander.RegisterCommand("fill", fillRegionCommand); + m_commander.RegisterCommand("elevate", elevateCommand); + m_commander.RegisterCommand("lower", lowerCommand); + m_commander.RegisterCommand("multiply", multiplyCommand); + m_commander.RegisterCommand("bake", bakeRegionCommand); + m_commander.RegisterCommand("revert", revertRegionCommand); + m_commander.RegisterCommand("newbrushes", experimentalBrushesCommand); + m_commander.RegisterCommand("stats", showDebugStatsCommand); + m_commander.RegisterCommand("effect", pluginRunCommand); + m_commander.RegisterCommand("flip", flipCommand); + + // Add this to our scene so scripts can call these functions + m_scene.RegisterModuleCommander(m_commander); + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs new file mode 100644 index 0000000..e7f92d7 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs @@ -0,0 +1,118 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using NUnit.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; + +namespace OpenSim.Region.CoreModules.World.Terrain.Tests +{ + [TestFixture] + public class TerrainTest + { + [Test] + public void BrushTest() + { + bool[,] allowMask = new bool[256, 256]; + int x; + int y; + for (x=0; x<128; x++) + { + for (y=0; y<256; y++) + { + allowMask[x,y] = true; + } + } + + // + // Test RaiseSphere + // + TerrainChannel map = new TerrainChannel(256, 256); + ITerrainPaintableEffect effect = new RaiseSphere(); + + effect.PaintEffect(map, allowMask, 128.0, 128.0, -1.0, 2, 0.1); + Assert.That(map[127, 128] > 0.0, "Raise brush should raising value at this point (127,128)."); + Assert.That(map[124, 128] > 0.0, "Raise brush should raising value at this point (124,128)."); + Assert.That(map[123, 128] == 0.0, "Raise brush should not change value at this point (123,128)."); + Assert.That(map[128, 128] == 0.0, "Raise brush should not change value at this point (128,128)."); + Assert.That(map[0, 128] == 0.0, "Raise brush should not change value at this point (0,128)."); + + // + // Test LowerSphere + // + map = new TerrainChannel(256, 256); + for (x=0; x= 0.0, "Lower should not lowering value below 0.0 at this point (127,128)."); + Assert.That(map[127, 128] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128)."); + Assert.That(map[124, 128] < 1.0, "Lower brush should lowering value at this point (124,128)."); + Assert.That(map[123, 128] == 1.0, "Lower brush should not change value at this point (123,128)."); + Assert.That(map[128, 128] == 1.0, "Lower brush should not change value at this point (128,128)."); + Assert.That(map[0, 128] == 1.0, "Lower brush should not change value at this point (0,128)."); + } + + [Test] + public void TerrainChannelTest() + { + TerrainChannel x = new TerrainChannel(256, 256); + Assert.That(x[0, 0] == 0.0, "Terrain not initialising correctly."); + + x[0, 0] = 1.0; + Assert.That(x[0, 0] == 1.0, "Terrain not setting values correctly."); + + x[0, 0] = 0; + x[0, 0] += 5.0; + x[0, 0] -= 1.0; + Assert.That(x[0, 0] == 4.0, "Terrain addition/subtraction error."); + + x[0, 0] = Math.PI; + double[,] doublesExport = x.GetDoubles(); + Assert.That(doublesExport[0, 0] == Math.PI, "Export to double[,] array not working correctly."); + + x[0, 0] = 1.0; + float[] floatsExport = x.GetFloatsSerialised(); + Assert.That(floatsExport[0] == 1.0f, "Export to float[] not working correctly."); + + x[0, 0] = 1.0; + Assert.That(x.Tainted(0, 0), "Terrain channel tainting not working correctly."); + Assert.That(!x.Tainted(0, 0), "Terrain channel tainting not working correctly."); + + TerrainChannel y = x.Copy(); + Assert.That(!ReferenceEquals(x, y), "Terrain copy not duplicating correctly."); + Assert.That(!ReferenceEquals(x.GetDoubles(), y.GetDoubles()), "Terrain array not duplicating correctly."); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs new file mode 100644 index 0000000..8b2bb1e --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs @@ -0,0 +1,118 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Vegetation +{ + public class VegetationModule : IRegionModule, IVegetationModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree }; + public PCode[] CreationCapabilities { get { return creationCapabilities; } } + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() {} + public void Close() {} + public string Name { get { return "Vegetation Module"; } } + public bool IsSharedModule { get { return false; } } + + public SceneObjectGroup AddTree( + UUID uuid, UUID groupID, Vector3 scale, Quaternion rotation, Vector3 position, Tree treeType, bool newTree) + { + PrimitiveBaseShape treeShape = new PrimitiveBaseShape(); + treeShape.PathCurve = 16; + treeShape.PathEnd = 49900; + treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree; + treeShape.Scale = scale; + treeShape.State = (byte)treeType; + + return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); + } + + public SceneObjectGroup CreateEntity( + UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) + { + if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0) + { + m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); + return null; + } + + SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); + SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID); + + // if grass or tree, make phantom + //rootPart.TrimPermissions(); + rootPart.AddFlag(PrimFlags.Phantom); + if (rootPart.Shape.PCode != (byte)PCode.Grass) + AdaptTree(ref shape); + + m_scene.AddNewSceneObject(sceneObject, true); + sceneObject.SetGroup(groupID, null); + + return sceneObject; + } + + protected void AdaptTree(ref PrimitiveBaseShape tree) + { + // Tree size has to be adapted depending on its type + switch ((Tree)tree.State) + { + case Tree.Cypress1: + case Tree.Cypress2: + tree.Scale = new Vector3(4, 4, 10); + break; + + // case... other tree types + // tree.Scale = new Vector3(?, ?, ?); + // break; + + default: + tree.Scale = new Vector3(4, 4, 4); + break; + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs new file mode 100644 index 0000000..b8bd605 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs @@ -0,0 +1,207 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules +{ + public class WindModule : IWindModule + { +// private static readonly log4net.ILog m_log +// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private int m_frame = 0; + private int m_frame_mod = 150; + private Random rndnums = new Random(System.Environment.TickCount); + private Scene m_scene = null; + private bool ready = false; + private Vector2[] windSpeeds = new Vector2[16 * 16]; + private Dictionary m_rootAgents = new Dictionary(); + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_frame = 0; + + scene.EventManager.OnFrame += WindUpdate; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; + scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; + scene.EventManager.OnClientClosed += ClientLoggedOut; + scene.RegisterModuleInterface(this); + + GenWindPos(); + + ready = true; + } + + public void PostInitialise() + { + } + + public void Close() + { + ready = false; + // Remove our hooks + m_scene.EventManager.OnFrame -= WindUpdate; + // m_scene.EventManager.OnNewClient -= SunToClient; + m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent; + m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; + m_scene.EventManager.OnClientClosed -= ClientLoggedOut; + } + + public string Name + { + get { return "WindModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public Vector2[] WindSpeeds + { + get { return windSpeeds; } + } + + public void WindToClient(IClientAPI client) + { + if (ready) + { + //if (!sunFixed) + //GenWindPos(); // Generate shared values once + client.SendWindData(windSpeeds); + } + } + + public void WindUpdate() + { + if (((m_frame++ % m_frame_mod) != 0) || !ready) + { + return; + } + //m_log.Debug("[WIND]:Regenerating..."); + GenWindPos(); // Generate shared values once + + //int spotxp = 0; + //int spotyp = 0; + //int spotxm = 0; + //int spotym = 0; + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence avatar in avatars) + { + if (!avatar.IsChildAgent) + { + avatar.ControllingClient.SendWindData(windSpeeds); + } + } + + // set estate settings for region access to sun position + //m_scene.RegionInfo.RegionSettings.SunVector = Position; + //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime(); + } + + public void ForceWindUpdateToAllClients() + { + GenWindPos(); // Generate shared values once + + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence avatar in avatars) + { + if (!avatar.IsChildAgent) + avatar.ControllingClient.SendWindData(windSpeeds); + } + + // set estate settings for region access to sun position + //m_scene.RegionInfo.RegionSettings.SunVector = Position; + //m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime(); + } + /// + /// Calculate the sun's orbital position and its velocity. + /// + + private void GenWindPos() + { + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x++) + { + windSpeeds[y * 16 + x].X = (float)(rndnums.NextDouble() * 2d - 1d); + windSpeeds[y * 16 + x].Y = (float)(rndnums.NextDouble() * 2d - 1d); + } + } + } + + private void ClientLoggedOut(UUID AgentId) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(AgentId)) + { + m_rootAgents.Remove(AgentId); + } + } + } + + private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + m_rootAgents[avatar.UUID] = avatar.RegionHandle; + } + else + { + m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); + WindToClient(avatar.ControllingClient); + } + } + //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); + } + + private void MakeChildAgent(ScenePresence avatar) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) + { + m_rootAgents.Remove(avatar.UUID); + } + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/WorldMap/IMapTileTerrainRenderer.cs b/OpenSim/Region/CoreModules/World/WorldMap/IMapTileTerrainRenderer.cs new file mode 100644 index 0000000..3684df0 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/WorldMap/IMapTileTerrainRenderer.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Drawing; +using OpenSim.Region.Framework.Scenes; +using Nini.Config; + +namespace OpenSim.Region.CoreModules.World.WorldMap +{ + public interface IMapTileTerrainRenderer + { + void Initialise(Scene scene, IConfigSource config); + void TerrainToBitmap(Bitmap mapbmp); + } +} diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs new file mode 100644 index 0000000..eea6cf6 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs @@ -0,0 +1,586 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Reflection; +using Nini.Config; +using OpenMetaverse.Imaging; +using log4net; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenMetaverse; + +namespace OpenSim.Region.CoreModules.World.WorldMap +{ + public enum DrawRoutine + { + Rectangle, + Polygon, + Ellipse + } + + public struct face + { + public Point[] pts; + } + + public struct DrawStruct + { + public DrawRoutine dr; + public Rectangle rect; + public SolidBrush brush; + public face[] trns; + } + + public class MapImageModule : IMapImageGenerator, IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private IConfigSource m_config; + private IMapTileTerrainRenderer terrainRenderer; + + #region IMapImageGenerator Members + + public byte[] WriteJpeg2000Image(string gradientmap) + { + byte[] imageData = null; + + bool drawPrimVolume = true; + bool textureTerrain = true; + + try + { + IConfig startupConfig = m_config.Configs["Startup"]; + drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume); + textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain); + } + catch + { + m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); + } + + if (textureTerrain) + { + terrainRenderer = new TexturedMapTileRenderer(); + } + else + { + terrainRenderer = new ShadedMapTileRenderer(); + } + terrainRenderer.Initialise(m_scene, m_config); + + Bitmap mapbmp = new Bitmap(256, 256); + //long t = System.Environment.TickCount; + //for (int i = 0; i < 10; ++i) { + terrainRenderer.TerrainToBitmap(mapbmp); + //} + //t = System.Environment.TickCount - t; + //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); + + + if (drawPrimVolume) + { + DrawObjectVolume(m_scene, mapbmp); + } + + try + { + imageData = OpenJPEG.EncodeFromImage(mapbmp, true); + } + catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke + { + Console.WriteLine("Failed generating terrain map: " + e); + } + + return imageData; + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + m_config = source; + + IConfig startupConfig = m_config.Configs["Startup"]; + if (startupConfig.GetString("MapImageModule", "MapImageModule") != + "MapImageModule") + return; + + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "MapImageModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + +// TODO: unused: +// private void ShadeBuildings(Bitmap map) +// { +// lock (map) +// { +// lock (m_scene.Entities) +// { +// foreach (EntityBase entity in m_scene.Entities.Values) +// { +// if (entity is SceneObjectGroup) +// { +// SceneObjectGroup sog = (SceneObjectGroup) entity; +// +// foreach (SceneObjectPart primitive in sog.Children.Values) +// { +// int x = (int) (primitive.AbsolutePosition.X - (primitive.Scale.X / 2)); +// int y = (int) (primitive.AbsolutePosition.Y - (primitive.Scale.Y / 2)); +// int w = (int) primitive.Scale.X; +// int h = (int) primitive.Scale.Y; +// +// int dx; +// for (dx = x; dx < x + w; dx++) +// { +// int dy; +// for (dy = y; dy < y + h; dy++) +// { +// if (x < 0 || y < 0) +// continue; +// if (x >= map.Width || y >= map.Height) +// continue; +// +// map.SetPixel(dx, dy, Color.DarkGray); +// } +// } +// } +// } +// } +// } +// } +// } + + private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp) + { + int tc = 0; + double[,] hm = whichScene.Heightmap.GetDoubles(); + tc = System.Environment.TickCount; + m_log.Info("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); + List objs = whichScene.GetEntities(); + Dictionary z_sort = new Dictionary(); + //SortedList z_sort = new SortedList(); + List z_sortheights = new List(); + List z_localIDs = new List(); + + lock (objs) + { + foreach (EntityBase obj in objs) + { + // Only draw the contents of SceneObjectGroup + if (obj is SceneObjectGroup) + { + SceneObjectGroup mapdot = (SceneObjectGroup)obj; + Color mapdotspot = Color.Gray; // Default color when prim color is white + // Loop over prim in group + foreach (SceneObjectPart part in mapdot.Children.Values) + { + if (part == null) + continue; + + // Draw if the object is at least 1 meter wide in any direction + if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) + { + // Try to get the RGBA of the default texture entry.. + // + try + { + // get the null checks out of the way + // skip the ones that break + if (part == null) + continue; + + if (part.Shape == null) + continue; + + if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass) + continue; // eliminates trees from this since we don't really have a good tree representation + // if you want tree blocks on the map comment the above line and uncomment the below line + //mapdotspot = Color.PaleGreen; + + if (part.Shape.Textures == null) + continue; + + if (part.Shape.Textures.DefaultTexture == null) + continue; + + Color4 texcolor = part.Shape.Textures.DefaultTexture.RGBA; + + // Not sure why some of these are null, oh well. + + int colorr = 255 - (int)(texcolor.R * 255f); + int colorg = 255 - (int)(texcolor.G * 255f); + int colorb = 255 - (int)(texcolor.B * 255f); + + if (!(colorr == 255 && colorg == 255 && colorb == 255)) + { + //Try to set the map spot color + try + { + // If the color gets goofy somehow, skip it *shakes fist at Color4 + mapdotspot = Color.FromArgb(colorr, colorg, colorb); + } + catch (ArgumentException) + { + } + } + } + catch (IndexOutOfRangeException) + { + // Windows Array + } + catch (ArgumentOutOfRangeException) + { + // Mono Array + } + + Vector3 pos = part.GetWorldPosition(); + + // skip prim outside of retion + if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f) + continue; + + // skip prim in non-finite position + if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) || + Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y)) + continue; + + // Figure out if object is under 256m above the height of the terrain + bool isBelow256AboveTerrain = false; + + try + { + isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f)); + } + catch (Exception) + { + } + + if (isBelow256AboveTerrain) + { + // Translate scale by rotation so scale is represented properly when object is rotated + Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z); + Vector3 scale = new Vector3(); + Vector3 tScale = new Vector3(); + Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z); + + Quaternion llrot = part.GetWorldRotation(); + Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z); + scale = lscale * rot; + + // negative scales don't work in this situation + scale.X = Math.Abs(scale.X); + scale.Y = Math.Abs(scale.Y); + scale.Z = Math.Abs(scale.Z); + + // This scaling isn't very accurate and doesn't take into account the face rotation :P + int mapdrawstartX = (int)(pos.X - scale.X); + int mapdrawstartY = (int)(pos.Y - scale.Y); + int mapdrawendX = (int)(pos.X + scale.X); + int mapdrawendY = (int)(pos.Y + scale.Y); + + // If object is beyond the edge of the map, don't draw it to avoid errors + if (mapdrawstartX < 0 || mapdrawstartX > 255 || mapdrawendX < 0 || mapdrawendX > 255 + || mapdrawstartY < 0 || mapdrawstartY > 255 || mapdrawendY < 0 + || mapdrawendY > 255) + continue; + +#region obb face reconstruction part duex + Vector3[] vertexes = new Vector3[8]; + + // float[] distance = new float[6]; + Vector3[] FaceA = new Vector3[6]; // vertex A for Facei + Vector3[] FaceB = new Vector3[6]; // vertex B for Facei + Vector3[] FaceC = new Vector3[6]; // vertex C for Facei + Vector3[] FaceD = new Vector3[6]; // vertex D for Facei + + tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z); + scale = ((tScale * rot)); + vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + // vertexes[0].x = pos.X + vertexes[0].x; + //vertexes[0].y = pos.Y + vertexes[0].y; + //vertexes[0].z = pos.Z + vertexes[0].z; + + FaceA[0] = vertexes[0]; + FaceB[3] = vertexes[0]; + FaceA[4] = vertexes[0]; + + tScale = lscale; + scale = ((tScale * rot)); + vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + + // vertexes[1].x = pos.X + vertexes[1].x; + // vertexes[1].y = pos.Y + vertexes[1].y; + //vertexes[1].z = pos.Z + vertexes[1].z; + + FaceB[0] = vertexes[1]; + FaceA[1] = vertexes[1]; + FaceC[4] = vertexes[1]; + + tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z); + scale = ((tScale * rot)); + + vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + + //vertexes[2].x = pos.X + vertexes[2].x; + //vertexes[2].y = pos.Y + vertexes[2].y; + //vertexes[2].z = pos.Z + vertexes[2].z; + + FaceC[0] = vertexes[2]; + FaceD[3] = vertexes[2]; + FaceC[5] = vertexes[2]; + + tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z); + scale = ((tScale * rot)); + vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + + //vertexes[3].x = pos.X + vertexes[3].x; + // vertexes[3].y = pos.Y + vertexes[3].y; + // vertexes[3].z = pos.Z + vertexes[3].z; + + FaceD[0] = vertexes[3]; + FaceC[1] = vertexes[3]; + FaceA[5] = vertexes[3]; + + tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z); + scale = ((tScale * rot)); + vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + + // vertexes[4].x = pos.X + vertexes[4].x; + // vertexes[4].y = pos.Y + vertexes[4].y; + // vertexes[4].z = pos.Z + vertexes[4].z; + + FaceB[1] = vertexes[4]; + FaceA[2] = vertexes[4]; + FaceD[4] = vertexes[4]; + + tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z); + scale = ((tScale * rot)); + vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + + // vertexes[5].x = pos.X + vertexes[5].x; + // vertexes[5].y = pos.Y + vertexes[5].y; + // vertexes[5].z = pos.Z + vertexes[5].z; + + FaceD[1] = vertexes[5]; + FaceC[2] = vertexes[5]; + FaceB[5] = vertexes[5]; + + tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z); + scale = ((tScale * rot)); + vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + + // vertexes[6].x = pos.X + vertexes[6].x; + // vertexes[6].y = pos.Y + vertexes[6].y; + // vertexes[6].z = pos.Z + vertexes[6].z; + + FaceB[2] = vertexes[6]; + FaceA[3] = vertexes[6]; + FaceB[4] = vertexes[6]; + + tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z); + scale = ((tScale * rot)); + vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); + + // vertexes[7].x = pos.X + vertexes[7].x; + // vertexes[7].y = pos.Y + vertexes[7].y; + // vertexes[7].z = pos.Z + vertexes[7].z; + + FaceD[2] = vertexes[7]; + FaceC[3] = vertexes[7]; + FaceD[5] = vertexes[7]; +#endregion + + //int wy = 0; + + //bool breakYN = false; // If we run into an error drawing, break out of the + // loop so we don't lag to death on error handling + DrawStruct ds = new DrawStruct(); + ds.brush = new SolidBrush(mapdotspot); + //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY); + + ds.trns = new face[FaceA.Length]; + + for (int i = 0; i < FaceA.Length; i++) + { + Point[] working = new Point[5]; + working[0] = project(FaceA[i], axPos); + working[1] = project(FaceB[i], axPos); + working[2] = project(FaceD[i], axPos); + working[3] = project(FaceC[i], axPos); + working[4] = project(FaceA[i], axPos); + + face workingface = new face(); + workingface.pts = working; + + ds.trns[i] = workingface; + } + + z_sort.Add(part.LocalId, ds); + z_localIDs.Add(part.LocalId); + z_sortheights.Add(pos.Z); + + //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) + //{ + //for (wy = mapdrawstartY; wy < mapdrawendY; wy++) + //{ + //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); + //try + //{ + // Remember, flip the y! + // mapbmp.SetPixel(wx, (255 - wy), mapdotspot); + //} + //catch (ArgumentException) + //{ + // breakYN = true; + //} + + //if (breakYN) + // break; + //} + + //if (breakYN) + // break; + //} + } // Object is within 256m Z of terrain + } // object is at least a meter wide + } // loop over group children + } // entitybase is sceneobject group + } // foreach loop over entities + + float[] sortedZHeights = z_sortheights.ToArray(); + uint[] sortedlocalIds = z_localIDs.ToArray(); + + // Sort prim by Z position + Array.Sort(sortedZHeights, sortedlocalIds); + + Graphics g = Graphics.FromImage(mapbmp); + + for (int s = 0; s < sortedZHeights.Length; s++) + { + if (z_sort.ContainsKey(sortedlocalIds[s])) + { + DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; + for (int r = 0; r < rectDrawStruct.trns.Length; r++ ) + { + g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); + } + //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect); + } + } + + g.Dispose(); + } // lock entities objs + + m_log.Info("[MAPTILE]: Generating Maptile Step 2: Done in " + (System.Environment.TickCount - tc) + " ms"); + return mapbmp; + } + + private Point project(Vector3 point3d, Vector3 originpos) + { + Point returnpt = new Point(); + //originpos = point3d; + //int d = (int)(256f / 1.5f); + + //Vector3 topos = new Vector3(0, 0, 0); + // float z = -point3d.z - topos.z; + + returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d); + returnpt.Y = (int)(255 - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d))); + + return returnpt; + } + +// TODO: unused: +// #region Deprecated Maptile Generation. Adam may update this +// private Bitmap TerrainToBitmap(string gradientmap) +// { +// Bitmap gradientmapLd = new Bitmap(gradientmap); +// +// int pallete = gradientmapLd.Height; +// +// Bitmap bmp = new Bitmap(m_scene.Heightmap.Width, m_scene.Heightmap.Height); +// Color[] colours = new Color[pallete]; +// +// for (int i = 0; i < pallete; i++) +// { +// colours[i] = gradientmapLd.GetPixel(0, i); +// } +// +// lock (m_scene.Heightmap) +// { +// ITerrainChannel copy = m_scene.Heightmap; +// for (int y = 0; y < copy.Height; y++) +// { +// for (int x = 0; x < copy.Width; x++) +// { +// // 512 is the largest possible height before colours clamp +// int colorindex = (int) (Math.Max(Math.Min(1.0, copy[x, y] / 512.0), 0.0) * (pallete - 1)); +// +// // Handle error conditions +// if (colorindex > pallete - 1 || colorindex < 0) +// bmp.SetPixel(x, copy.Height - y - 1, Color.Red); +// else +// bmp.SetPixel(x, copy.Height - y - 1, colours[colorindex]); +// } +// } +// ShadeBuildings(bmp); +// return bmp; +// } +// } +// #endregion + } +} diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs new file mode 100644 index 0000000..45a99a9 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs @@ -0,0 +1,172 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Reflection; +using System.Collections.Generic; +using System.Net; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Hypergrid; +using OpenMetaverse; +using log4net; +using Nini.Config; + +namespace OpenSim.Region.CoreModules.World.WorldMap +{ + public class MapSearchModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + Scene m_scene = null; // only need one for communication with GridService + List m_scenes = new List(); + + #region IRegionModule Members + public void Initialise(Scene scene, IConfigSource source) + { + if (m_scene == null) + { + m_scene = scene; + } + + m_scenes.Add(scene); + scene.EventManager.OnNewClient += OnNewClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + m_scene = null; + m_scenes.Clear(); + } + + public string Name + { + get { return "MapSearchModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void OnNewClient(IClientAPI client) + { + client.OnMapNameRequest += OnMapNameRequest; + } + + private void OnMapNameRequest(IClientAPI remoteClient, string mapName) + { + if (mapName.Length < 3) + { + remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); + return; + } + + // try to fetch from GridServer + List regionInfos = m_scene.SceneGridService.RequestNamedRegions(mapName, 20); + if (regionInfos == null) + { + m_log.Warn("[MAPSEARCHMODULE]: RequestNamedRegions returned null. Old gridserver?"); + // service wasn't available; maybe still an old GridServer. Try the old API, though it will return only one region + regionInfos = new List(); + RegionInfo info = m_scene.SceneGridService.RequestClosestRegion(mapName); + if (info != null) regionInfos.Add(info); + } + + if ((regionInfos.Count == 0) && IsHypergridOn()) + { + // OK, we tried but there are no regions matching that name. + // Let's check quickly if this is a domain name, and if so link to it + if (mapName.Contains(".") && mapName.Contains(":")) + { + // It probably is a domain name. Try to link to it. + RegionInfo regInfo; + Scene cScene = GetClientScene(remoteClient); + regInfo = HGHyperlink.TryLinkRegion(cScene, remoteClient, mapName); + if (regInfo != null) + regionInfos.Add(regInfo); + } + } + + List blocks = new List(); + + MapBlockData data; + if (regionInfos.Count > 0) + { + foreach (RegionInfo info in regionInfos) + { + data = new MapBlockData(); + data.Agents = 0; + data.Access = 21; // TODO what's this? + data.MapImageId = info.RegionSettings.TerrainImageID; + data.Name = info.RegionName; + data.RegionFlags = 0; // TODO not used? + data.WaterHeight = 0; // not used + data.X = (ushort)info.RegionLocX; + data.Y = (ushort)info.RegionLocY; + blocks.Add(data); + } + } + + // final block, closing the search result + data = new MapBlockData(); + data.Agents = 0; + data.Access = 255; + data.MapImageId = UUID.Zero; + data.Name = mapName; + data.RegionFlags = 0; + data.WaterHeight = 0; // not used + data.X = 0; + data.Y = 0; + blocks.Add(data); + + remoteClient.SendMapBlock(blocks, 0); + } + + private bool IsHypergridOn() + { + return (m_scene.SceneGridService is HGSceneCommunicationService); + } + + private Scene GetClientScene(IClientAPI client) + { + foreach (Scene s in m_scenes) + { + if (client.Scene.RegionInfo.RegionHandle == s.RegionInfo.RegionHandle) + return s; + } + return m_scene; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs new file mode 100644 index 0000000..b783d7c --- /dev/null +++ b/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs @@ -0,0 +1,249 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Reflection; +using OpenMetaverse; +using OpenMetaverse.Imaging; +using Nini.Config; +using log4net; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.WorldMap +{ + public class ShadedMapTileRenderer : IMapTileTerrainRenderer + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + //private IConfigSource m_config; // not used currently + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + // m_config = config; // not used currently + } + + public void TerrainToBitmap(Bitmap mapbmp) + { + int tc = System.Environment.TickCount; + m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); + + double[,] hm = m_scene.Heightmap.GetDoubles(); + bool ShadowDebugContinue = true; + + bool terraincorruptedwarningsaid = false; + + float low = 255; + float high = 0; + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + float hmval = (float)hm[x, y]; + if (hmval < low) + low = hmval; + if (hmval > high) + high = hmval; + } + } + + float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; + + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left + int yr = 255 - y; + + float heightvalue = (float)hm[x, y]; + + if (heightvalue > waterHeight) + { + // scale height value + // No, that doesn't scale it: + // heightvalue = low + mid * (heightvalue - low) / mid; => low + (heightvalue - low) * mid / mid = low + (heightvalue - low) * 1 = low + heightvalue - low = heightvalue + + if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) + heightvalue = 0; + else if (heightvalue > 255f) + heightvalue = 255f; + else if (heightvalue < 0f) + heightvalue = 0f; + + Color color = Color.FromArgb((int)heightvalue, 100, (int)heightvalue); + + mapbmp.SetPixel(x, yr, color); + + try + { + //X + // . + // + // Shade the terrain for shadows + if (x < 255 && yr < 255) + { + float hfvalue = (float)hm[x, y]; + float hfvaluecompare = 0f; + + if ((x + 1 < 256) && (y + 1 < 256)) + { + hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there + } + if (Single.IsInfinity(hfvalue) || Single.IsNaN(hfvalue)) + hfvalue = 0f; + + if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare)) + hfvaluecompare = 0f; + + float hfdiff = hfvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower + + int hfdiffi = 0; + int hfdiffihighlight = 0; + float highlightfactor = 0.18f; + + try + { + // hfdiffi = Math.Abs((int)((hfdiff * 4) + (hfdiff * 0.5))) + 1; + hfdiffi = Math.Abs((int)(hfdiff * 4.5f)) + 1; + if (hfdiff % 1f != 0) + { + // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1); + hfdiffi = hfdiffi + Math.Abs((int)((hfdiff % 1f) * 5f) - 1); + } + + hfdiffihighlight = Math.Abs((int)((hfdiff * highlightfactor) * 4.5f)) + 1; + if (hfdiff % 1f != 0) + { + // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1); + hfdiffihighlight = hfdiffihighlight + Math.Abs((int)(((hfdiff * highlightfactor) % 1f) * 5f) - 1); + } + } + catch (System.OverflowException) + { + m_log.Debug("[MAPTILE]: Shadow failed at value: " + hfdiff.ToString()); + ShadowDebugContinue = false; + } + + if (hfdiff > 0.3f) + { + // NE is lower than here + // We have to desaturate and lighten the land at the same time + // we use floats, colors use bytes, so shrink are space down to + // 0-255 + + if (ShadowDebugContinue) + { + int r = color.R; + int g = color.G; + int b = color.B; + color = Color.FromArgb((r + hfdiffihighlight < 255) ? r + hfdiffihighlight : 255, + (g + hfdiffihighlight < 255) ? g + hfdiffihighlight : 255, + (b + hfdiffihighlight < 255) ? b + hfdiffihighlight : 255); + } + } + else if (hfdiff < -0.3f) + { + // here is lower than NE: + // We have to desaturate and blacken the land at the same time + // we use floats, colors use bytes, so shrink are space down to + // 0-255 + + if (ShadowDebugContinue) + { + if ((x - 1 > 0) && (yr + 1 < 256)) + { + color = mapbmp.GetPixel(x - 1, yr + 1); + int r = color.R; + int g = color.G; + int b = color.B; + color = Color.FromArgb((r - hfdiffi > 0) ? r - hfdiffi : 0, + (g - hfdiffi > 0) ? g - hfdiffi : 0, + (b - hfdiffi > 0) ? b - hfdiffi : 0); + + mapbmp.SetPixel(x-1, yr+1, color); + } + } + } + } + } + catch (System.ArgumentException) + { + if (!terraincorruptedwarningsaid) + { + m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); + terraincorruptedwarningsaid = true; + } + color = Color.Black; + mapbmp.SetPixel(x, yr, color); + } + } + else + { + // We're under the water level with the terrain, so paint water instead of land + + // Y flip the cordinates + heightvalue = waterHeight - heightvalue; + if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) + heightvalue = 0f; + else if (heightvalue > 19f) + heightvalue = 19f; + else if (heightvalue < 0f) + heightvalue = 0f; + + heightvalue = 100f - (heightvalue * 100f) / 19f; + + try + { + Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255); + mapbmp.SetPixel(x, yr, water); + } + catch (System.ArgumentException) + { + if (!terraincorruptedwarningsaid) + { + m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); + terraincorruptedwarningsaid = true; + } + Color black = Color.Black; + mapbmp.SetPixel(x, (256 - y) - 1, black); + } + } + } + } + m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms"); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs new file mode 100644 index 0000000..537644a --- /dev/null +++ b/OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs @@ -0,0 +1,411 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Reflection; +using OpenMetaverse; +using Nini.Config; +using log4net; +using OpenMetaverse.Imaging; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Terrain; + +namespace OpenSim.Region.CoreModules.World.WorldMap +{ + // Hue, Saturation, Value; used for color-interpolation + struct HSV { + public float h; + public float s; + public float v; + + public HSV(float h, float s, float v) + { + this.h = h; + this.s = s; + this.v = v; + } + + // (for info about algorithm, see http://en.wikipedia.org/wiki/HSL_and_HSV) + public HSV(Color c) + { + float r = c.R / 255f; + float g = c.G / 255f; + float b = c.B / 255f; + float max = Math.Max(Math.Max(r, g), b); + float min = Math.Min(Math.Min(r, g), b); + float diff = max - min; + + if (max == min) h = 0f; + else if (max == r) h = (g - b) / diff * 60f; + else if (max == g) h = (b - r) / diff * 60f + 120f; + else h = (r - g) / diff * 60f + 240f; + if (h < 0f) h += 360f; + + if (max == 0f) s = 0f; + else s = diff / max; + + v = max; + } + + // (for info about algorithm, see http://en.wikipedia.org/wiki/HSL_and_HSV) + public Color toColor() + { + if (s < 0f) Console.WriteLine("S < 0: " + s); + else if (s > 1f) Console.WriteLine("S > 1: " + s); + if (v < 0f) Console.WriteLine("V < 0: " + v); + else if (v > 1f) Console.WriteLine("V > 1: " + v); + + float f = h / 60f; + int sector = (int)f % 6; + f = f - (int)f; + int pi = (int)(v * (1f - s) * 255f); + int qi = (int)(v * (1f - s * f) * 255f); + int ti = (int)(v * (1f - (1f - f) * s) * 255f); + int vi = (int)(v * 255f); + + switch (sector) + { + case 0: + return Color.FromArgb(vi, ti, pi); + case 1: + return Color.FromArgb(qi, vi, pi); + case 2: + return Color.FromArgb(pi, vi, ti); + case 3: + return Color.FromArgb(pi, qi, vi); + case 4: + return Color.FromArgb(ti, pi, vi); + default: + return Color.FromArgb(vi, pi, qi); + } + } + } + + public class TexturedMapTileRenderer : IMapTileTerrainRenderer + { + #region Constants + + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank"). + // The color-values were choosen because they "look right" (at least to me) ;-) + private static readonly UUID defaultTerrainTexture1 = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5"); + private static readonly Color defaultColor1 = Color.FromArgb(165, 137, 118); + private static readonly UUID defaultTerrainTexture2 = new UUID("63338ede-0037-c4fd-855b-015d77112fc8"); + private static readonly Color defaultColor2 = Color.FromArgb(69, 89, 49); + private static readonly UUID defaultTerrainTexture3 = new UUID("303cd381-8560-7579-23f1-f0a880799740"); + private static readonly Color defaultColor3 = Color.FromArgb(162, 154, 141); + private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c"); + private static readonly Color defaultColor4 = Color.FromArgb(200, 200, 200); + + #endregion + + + private Scene m_scene; + // private IConfigSource m_config; // not used currently + + // mapping from texture UUIDs to averaged color. This will contain 5-9 values, in general; new values are only + // added when the terrain textures are changed in the estate dialog and a new map is generated (and will stay in + // that map until the region-server restarts. This could be considered a memory-leak, but it's a *very* small one. + // TODO does it make sense to use a "real" cache and regenerate missing entries on fetch? + private Dictionary m_mapping; + + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + // m_config = source; // not used currently + m_mapping = new Dictionary(); + m_mapping.Add(defaultTerrainTexture1, defaultColor1); + m_mapping.Add(defaultTerrainTexture2, defaultColor2); + m_mapping.Add(defaultTerrainTexture3, defaultColor3); + m_mapping.Add(defaultTerrainTexture4, defaultColor4); + m_mapping.Add(Util.BLANK_TEXTURE_UUID, Color.White); + } + + #region Helpers + // This fetches the texture from the asset server synchroneously. That should be ok, as we + // call map-creation only in those places: + // - on start: We can wait here until the asset server returns the texture + // TODO (- on "map" command: We are in the command-line thread, we will wait for completion anyway) + // TODO (- on "automatic" update after some change: We are called from the mapUpdateTimer here and + // will wait anyway) + private Bitmap fetchTexture(UUID id) + { + AssetBase asset = m_scene.AssetCache.GetAsset(id, true); + m_log.DebugFormat("Fetched texture {0}, found: {1}", id, asset != null); + if (asset == null) return null; + + ManagedImage managedImage; + Image image; + + try + { + if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image)) + return new Bitmap(image); + else + return null; + } + catch (DllNotFoundException) + { + m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is emtpy for {0}", id); + + } + catch (IndexOutOfRangeException) + { + m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id); + + } + catch (Exception) + { + m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id); + + } + return null; + + } + + // Compute the average color of a texture. + private Color computeAverageColor(Bitmap bmp) + { + // we have 256 x 256 pixel, each with 256 possible color-values per + // color-channel, so 2^24 is the maximum value we can get, adding everything. + // int is be big enough for that. + int r = 0, g = 0, b = 0; + for (int y = 0; y < bmp.Height; ++y) + { + for (int x = 0; x < bmp.Width; ++x) + { + Color c = bmp.GetPixel(x, y); + r += (int)c.R & 0xff; + g += (int)c.G & 0xff; + b += (int)c.B & 0xff; + } + } + + int pixels = bmp.Width * bmp.Height; + return Color.FromArgb(r / pixels, g / pixels, b / pixels); + } + + // return either the average color of the texture, or the defaultColor if the texturID is invalid + // or the texture couldn't be found + private Color computeAverageColor(UUID textureID, Color defaultColor) { + if (textureID == UUID.Zero) return defaultColor; // not set + if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures + + Bitmap bmp = fetchTexture(textureID); + Color color = bmp == null ? defaultColor : computeAverageColor(bmp); + // store it for future reference + m_mapping[textureID] = color; + + return color; + } + + // S-curve: f(x) = 3x² - 2x³: + // f(0) = 0, f(0.5) = 0.5, f(1) = 1, + // f'(x) = 0 at x = 0 and x = 1; f'(0.5) = 1.5, + // f''(0.5) = 0, f''(x) != 0 for x != 0.5 + private float S(float v) { + return (v * v * (3f - 2f * v)); + } + + // interpolate two colors in HSV space and return the resulting color + private HSV interpolateHSV(ref HSV c1, ref HSV c2, float ratio) { + if (ratio <= 0f) return c1; + if (ratio >= 1f) return c2; + + // make sure we are on the same side on the hue-circle for interpolation + // We change the hue of the parameters here, but we don't change the color + // represented by that value + if (c1.h - c2.h > 180f) c1.h -= 360f; + else if (c2.h - c1.h > 180f) c1.h += 360f; + + return new HSV(c1.h * (1f - ratio) + c2.h * ratio, + c1.s * (1f - ratio) + c2.s * ratio, + c1.v * (1f - ratio) + c2.v * ratio); + } + + // the heigthfield might have some jumps in values. Rendered land is smooth, though, + // as a slope is rendered at that place. So average 4 neighbour values to emulate that. + private float getHeight(double[,] hm, int x, int y) { + if (x < 255 && y < 255) + return (float)(hm[x, y] * .444 + (hm[x + 1, y] + hm[x, y + 1]) * .222 + hm[x + 1, y +1] * .112); + else + return (float)hm[x, y]; + } + #endregion + + public void TerrainToBitmap(Bitmap mapbmp) + { + int tc = System.Environment.TickCount; + m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); + + // These textures should be in the AssetCache anyway, as every client conneting to this + // region needs them. Except on start, when the map is recreated (before anyone connected), + // and on change of the estate settings (textures and terrain values), when the map should + // be recreated. + RegionSettings settings = m_scene.RegionInfo.RegionSettings; + + // the four terrain colors as HSVs for interpolation + HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, defaultColor1)); + HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, defaultColor2)); + HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, defaultColor3)); + HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, defaultColor4)); + + float levelNElow = (float)settings.Elevation1NE; + float levelNEhigh = (float)settings.Elevation2NE; + + float levelNWlow = (float)settings.Elevation1NW; + float levelNWhigh = (float)settings.Elevation2NW; + + float levelSElow = (float)settings.Elevation1SE; + float levelSEhigh = (float)settings.Elevation2SE; + + float levelSWlow = (float)settings.Elevation1SW; + float levelSWhigh = (float)settings.Elevation2SW; + + float waterHeight = (float)settings.WaterHeight; + + double[,] hm = m_scene.Heightmap.GetDoubles(); + + for (int x = 0; x < 256; x++) + { + float columnRatio = x / 255f; // 0 - 1, for interpolation + for (int y = 0; y < 256; y++) + { + float rowRatio = y / 255f; // 0 - 1, for interpolation + + // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left + int yr = 255 - y; + + float heightvalue = getHeight(hm, x, y); + if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) + heightvalue = 0; + + if (heightvalue > waterHeight) + { + // add a bit noise for breaking up those flat colors: + // - a large-scale noise, for the "patches" (using an doubled s-curve for sharper contrast) + // - a small-scale noise, for bringing in some small scale variation + //float bigNoise = (float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f; // map to 0.0 - 1.0 + //float smallNoise = (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * .5f + .5f; + //float hmod = heightvalue + smallNoise * 3f + S(S(bigNoise)) * 10f; + float hmod = + heightvalue + + (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * 1.5f + 1.5f + // 0 - 3 + S(S((float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f)) * 10f; // 0 - 10 + + // find the low/high values for this point (interpolated bilinearily) + // (and remember, x=0,y=0 is SW) + float low = levelSWlow * (1f - rowRatio) * (1f - columnRatio) + + levelSElow * (1f - rowRatio) * columnRatio + + levelNWlow * rowRatio * (1f - columnRatio) + + levelNElow * rowRatio * columnRatio; + float high = levelSWhigh * (1f - rowRatio) * (1f - columnRatio) + + levelSEhigh * (1f - rowRatio) * columnRatio + + levelNWhigh * rowRatio * (1f - columnRatio) + + levelNEhigh * rowRatio * columnRatio; + if (high < low) + { + // someone tried to fool us. High value should be higher than low every time + float tmp = high; + high = low; + low = tmp; + } + + HSV hsv; + if (hmod <= low) hsv = hsv1; // too low + else if (hmod >= high) hsv = hsv4; // too high + else + { + // HSV-interpolate along the colors + // first, rescale h to 0.0 - 1.0 + hmod = (hmod - low) / (high - low); + // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 + if (hmod < 1f/3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f); + else if (hmod < 2f/3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f); + else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f); + } + + // Shade the terrain for shadows + if (x < 255 && y < 255) + { + float hfvaluecompare = getHeight(hm, x + 1, y + 1); // light from north-east => look at land height there + if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare)) + hfvaluecompare = 0f; + + float hfdiff = heightvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower + hfdiff *= 0.06f; // some random factor so "it looks good" + if (hfdiff > 0.02f) + { + float highlightfactor = 0.18f; + // NE is lower than here + // We have to desaturate and lighten the land at the same time + hsv.s = (hsv.s - (hfdiff * highlightfactor) > 0f) ? hsv.s - (hfdiff * highlightfactor) : 0f; + hsv.v = (hsv.v + (hfdiff * highlightfactor) < 1f) ? hsv.v + (hfdiff * highlightfactor) : 1f; + } + else if (hfdiff < -0.02f) + { + // here is lower than NE: + // We have to desaturate and blacken the land at the same time + hsv.s = (hsv.s + hfdiff > 0f) ? hsv.s + hfdiff : 0f; + hsv.v = (hsv.v + hfdiff > 0f) ? hsv.v + hfdiff : 0f; + } + } + mapbmp.SetPixel(x, yr, hsv.toColor()); + } + else + { + // We're under the water level with the terrain, so paint water instead of land + + heightvalue = waterHeight - heightvalue; + if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) + heightvalue = 0f; + else if (heightvalue > 19f) + heightvalue = 19f; + else if (heightvalue < 0f) + heightvalue = 0f; + + heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0 + + Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255); + mapbmp.SetPixel(x, yr, water); + } + } + } + m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms"); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs new file mode 100644 index 0000000..376e365 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -0,0 +1,905 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Net; +using System.Reflection; +using System.Threading; +using OpenMetaverse; +using OpenMetaverse.Imaging; +using OpenMetaverse.StructuredData; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Types; +using Caps = OpenSim.Framework.Communications.Capabilities.Caps; + +using OSD = OpenMetaverse.StructuredData.OSD; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; + +namespace OpenSim.Region.CoreModules.World.WorldMap +{ + public class WorldMapModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly string m_mapLayerPath = "0001/"; + + private OpenSim.Framework.BlockingQueue requests = new OpenSim.Framework.BlockingQueue(); + + //private IConfig m_config; + protected Scene m_scene; + private List cachedMapBlocks = new List(); + private int cachedTime = 0; + private byte[] myMapImageJPEG; + protected bool m_Enabled = false; + private Dictionary m_openRequests = new Dictionary(); + private Dictionary m_blacklistedurls = new Dictionary(); + private Dictionary m_blacklistedregions = new Dictionary(); + private Dictionary m_cachedRegionMapItemsAddress = new Dictionary(); + private List m_rootAgents = new List(); + private Thread mapItemReqThread; + private volatile bool threadrunning = false; + + //private int CacheRegionsDistance = 256; + + #region IRegionModule Members + + public virtual void Initialise(Scene scene, IConfigSource config) + { + IConfig startupConfig = config.Configs["Startup"]; + if (startupConfig.GetString("WorldMapModule", "WorldMap") == + "WorldMap") + m_Enabled = true; + + if (!m_Enabled) + return; + + m_scene = scene; + } + + public virtual void PostInitialise() + { + if (m_Enabled) + AddHandlers(); + } + + public virtual void Close() + { + } + + public virtual string Name + { + get { return "WorldMapModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + protected virtual void AddHandlers() + { + myMapImageJPEG = new byte[0]; + + string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); + regionimage = regionimage.Replace("-", ""); + m_log.Info("[WORLD MAP]: JPEG Map location: http://" + m_scene.RegionInfo.ExternalEndPoint.Address.ToString() + ":" + m_scene.RegionInfo.HttpPort.ToString() + "/index.php?method=" + regionimage); + + m_scene.CommsManager.HttpServer.AddHTTPHandler(regionimage, OnHTTPGetMapImage); + m_scene.CommsManager.HttpServer.AddLLSDHandler( + "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); + + m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; + m_scene.EventManager.OnNewClient += OnNewClient; + m_scene.EventManager.OnClientClosed += ClientLoggedOut; + m_scene.EventManager.OnMakeChildAgent += MakeChildAgent; + m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; + } + + public void OnRegisterCaps(UUID agentID, Caps caps) + { + //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); + string capsBase = "/CAPS/" + caps.CapsObjectPath; + caps.RegisterHandler("MapLayer", + new RestStreamHandler("POST", capsBase + m_mapLayerPath, + delegate(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return MapLayerRequest(request, path, param, + agentID, caps); + })); + } + + /// + /// Callback for a map layer request + /// + /// + /// + /// + /// + /// + /// + public string MapLayerRequest(string request, string path, string param, + UUID agentID, Caps caps) + { + //try + //{ + //m_log.DebugFormat("[MAPLAYER]: request: {0}, path: {1}, param: {2}, agent:{3}", + //request, path, param,agentID.ToString()); + + // this is here because CAPS map requests work even beyond the 10,000 limit. + ScenePresence avatarPresence = null; + + m_scene.TryGetAvatar(agentID, out avatarPresence); + + if (avatarPresence != null) + { + bool lookup = false; + + lock (cachedMapBlocks) + { + if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) + { + List mapBlocks; + + mapBlocks = cachedMapBlocks; + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + } + else + { + lookup = true; + } + } + if (lookup) + { + List mapBlocks; + + mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks((int)m_scene.RegionInfo.RegionLocX - 8, (int)m_scene.RegionInfo.RegionLocY - 8, (int)m_scene.RegionInfo.RegionLocX + 8, (int)m_scene.RegionInfo.RegionLocY + 8); + avatarPresence.ControllingClient.SendMapBlock(mapBlocks,0); + + lock (cachedMapBlocks) + cachedMapBlocks = mapBlocks; + + cachedTime = Util.UnixTimeSinceEpoch(); + } + } + LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); + mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); + return mapResponse.ToString(); + } + + /// + /// + /// + /// + /// + public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq) + { + m_log.Debug("[WORLD MAP]: MapLayer Request in region: " + m_scene.RegionInfo.RegionName); + LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); + mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); + return mapResponse; + } + + /// + /// + /// + /// + protected static OSDMapLayer GetOSDMapLayerResponse() + { + OSDMapLayer mapLayer = new OSDMapLayer(); + mapLayer.Right = 5000; + mapLayer.Top = 5000; + mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); + + return mapLayer; + } + #region EventHandlers + + /// + /// Registered for event + /// + /// + private void OnNewClient(IClientAPI client) + { + client.OnRequestMapBlocks += RequestMapBlocks; + client.OnMapItemRequest += HandleMapItemRequest; + } + + /// + /// Client logged out, check to see if there are any more root agents in the simulator + /// If not, stop the mapItemRequest Thread + /// Event handler + /// + /// AgentID that logged out + private void ClientLoggedOut(UUID AgentId) + { + List presences = m_scene.GetAvatars(); + int rootcount = 0; + for (int i=0;i + /// Starts the MapItemRequest Thread + /// Note that this only gets started when there are actually agents in the region + /// Additionally, it gets stopped when there are none. + /// + /// + private void StartThread(object o) + { + if (threadrunning) return; + threadrunning = true; + m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread"); + mapItemReqThread = new Thread(new ThreadStart(process)); + mapItemReqThread.IsBackground = true; + mapItemReqThread.Name = "MapItemRequestThread"; + mapItemReqThread.Priority = ThreadPriority.BelowNormal; + mapItemReqThread.SetApartmentState(ApartmentState.MTA); + mapItemReqThread.Start(); + ThreadTracker.Add(mapItemReqThread); + } + + /// + /// Enqueues a 'stop thread' MapRequestState. Causes the MapItemRequest thread to end + /// + private void StopThread() + { + MapRequestState st = new MapRequestState(); + st.agentID=UUID.Zero; + st.EstateID=0; + st.flags=0; + st.godlike=false; + st.itemtype=0; + st.regionhandle=0; + + requests.Enqueue(st); + } + + public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, + uint EstateID, bool godlike, uint itemtype, ulong regionhandle) + { + lock (m_rootAgents) + { + if (!m_rootAgents.Contains(remoteClient.AgentId)) + return; + } + uint xstart = 0; + uint ystart = 0; + Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); + if (itemtype == 6) // we only sevice 6 right now (avatar green dots) + { + if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) + { + // Local Map Item Request + List avatars = m_scene.GetAvatars(); + int tc = System.Environment.TickCount; + List mapitems = new List(); + mapItemReply mapitem = new mapItemReply(); + if (avatars.Count == 0 || avatars.Count == 1) + { + mapitem = new mapItemReply(); + mapitem.x = (uint)(xstart + 1); + mapitem.y = (uint)(ystart + 1); + mapitem.id = UUID.Zero; + mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()); + mapitem.Extra = 0; + mapitem.Extra2 = 0; + mapitems.Add(mapitem); + } + else + { + foreach (ScenePresence av in avatars) + { + // Don't send a green dot for yourself + if (av.UUID != remoteClient.AgentId) + { + mapitem = new mapItemReply(); + mapitem.x = (uint)(xstart + av.AbsolutePosition.X); + mapitem.y = (uint)(ystart + av.AbsolutePosition.Y); + mapitem.id = UUID.Zero; + mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()); + mapitem.Extra = 1; + mapitem.Extra2 = 0; + mapitems.Add(mapitem); + } + } + } + remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); + } + else + { + // Remote Map Item Request + + // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. + // Note that we only start up a remote mapItem Request thread if there's users who could + // be making requests + if (!threadrunning) + { + m_log.Warn("[WORLD MAP]: Starting new remote request thread manually. This means that AvatarEnteringParcel never fired! This needs to be fixed! Don't Mantis this, as the developers can see it in this message"); + StartThread(new object()); + } + + RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); + } + } + } + + /// + /// Processing thread main() loop for doing remote mapitem requests + /// + public void process() + { + try + { + while (true) + { + MapRequestState st = requests.Dequeue(); + + // end gracefully + if (st.agentID == UUID.Zero) + { + ThreadTracker.Remove(mapItemReqThread); + break; + } + + bool dorequest = true; + lock (m_rootAgents) + { + if (!m_rootAgents.Contains(st.agentID)) + dorequest = false; + } + + if (dorequest) + { + OSDMap response = RequestMapItemsAsync("", st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); + RequestMapItemsCompleted(response); + } + } + } + catch (Exception e) + { + m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e); + } + + threadrunning = false; + } + + /// + /// Enqueues the map item request into the processing thread + /// + /// + public void EnqueueMapItemRequest(MapRequestState state) + { + requests.Enqueue(state); + } + + /// + /// Sends the mapitem response to the IClientAPI + /// + /// The OSDMap Response for the mapitem + private void RequestMapItemsCompleted(OSDMap response) + { + UUID requestID = response["requestID"].AsUUID(); + + if (requestID != UUID.Zero) + { + MapRequestState mrs = new MapRequestState(); + mrs.agentID = UUID.Zero; + lock (m_openRequests) + { + if (m_openRequests.ContainsKey(requestID)) + { + mrs = m_openRequests[requestID]; + m_openRequests.Remove(requestID); + } + } + + if (mrs.agentID != UUID.Zero) + { + ScenePresence av = null; + m_scene.TryGetAvatar(mrs.agentID, out av); + if (av != null) + { + if (response.ContainsKey(mrs.itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags); + } + } + } + } + } + + /// + /// Enqueue the MapItem request for remote processing + /// + /// blank string, we discover this in the process + /// Agent ID that we are making this request on behalf + /// passed in from packet + /// passed in from packet + /// passed in from packet + /// passed in from packet + /// Region we're looking up + public void RequestMapItems(string httpserver, UUID id, uint flags, + uint EstateID, bool godlike, uint itemtype, ulong regionhandle) + { + MapRequestState st = new MapRequestState(); + st.agentID = id; + st.flags = flags; + st.EstateID = EstateID; + st.godlike = godlike; + st.itemtype = itemtype; + st.regionhandle = regionhandle; + EnqueueMapItemRequest(st); + } + + /// + /// Does the actual remote mapitem request + /// This should be called from an asynchronous thread + /// Request failures get blacklisted until region restart so we don't + /// continue to spend resources trying to contact regions that are down. + /// + /// blank string, we discover this in the process + /// Agent ID that we are making this request on behalf + /// passed in from packet + /// passed in from packet + /// passed in from packet + /// passed in from packet + /// Region we're looking up + /// + private OSDMap RequestMapItemsAsync(string httpserver, UUID id, uint flags, + uint EstateID, bool godlike, uint itemtype, ulong regionhandle) + { + bool blacklisted = false; + lock (m_blacklistedregions) + { + if (m_blacklistedregions.ContainsKey(regionhandle)) + blacklisted = true; + } + + if (blacklisted) + return new OSDMap(); + + UUID requestID = UUID.Random(); + lock (m_cachedRegionMapItemsAddress) + { + if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) + httpserver = m_cachedRegionMapItemsAddress[regionhandle]; + } + if (httpserver.Length == 0) + { + RegionInfo mreg = m_scene.SceneGridService.RequestNeighbouringRegionInfo(regionhandle); + + if (mreg != null) + { + httpserver = "http://" + mreg.ExternalEndPoint.Address.ToString() + ":" + mreg.HttpPort + "/MAP/MapItems/" + regionhandle.ToString(); + lock (m_cachedRegionMapItemsAddress) + { + if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) + m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver); + } + } + else + { + lock (m_blacklistedregions) + { + if (!m_blacklistedregions.ContainsKey(regionhandle)) + m_blacklistedregions.Add(regionhandle, System.Environment.TickCount); + } + m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString()); + } + } + + blacklisted = false; + lock (m_blacklistedurls) + { + if (m_blacklistedurls.ContainsKey(httpserver)) + blacklisted = true; + } + + // Can't find the http server + if (httpserver.Length == 0 || blacklisted) + return new OSDMap(); + + MapRequestState mrs = new MapRequestState(); + mrs.agentID = id; + mrs.EstateID = EstateID; + mrs.flags = flags; + mrs.godlike = godlike; + mrs.itemtype=itemtype; + mrs.regionhandle = regionhandle; + + lock (m_openRequests) + m_openRequests.Add(requestID, mrs); + + WebRequest mapitemsrequest = WebRequest.Create(httpserver); + mapitemsrequest.Method = "POST"; + mapitemsrequest.ContentType = "application/xml+llsd"; + OSDMap RAMap = new OSDMap(); + + // string RAMapString = RAMap.ToString(); + OSD LLSDofRAMap = RAMap; // RENAME if this works + + byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); + OSDMap responseMap = new OSDMap(); + responseMap["requestID"] = OSD.FromUUID(requestID); + + Stream os = null; + try + { // send the Post + mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send + os = mapitemsrequest.GetRequestStream(); + os.Write(buffer, 0, buffer.Length); //Send it + os.Close(); + //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from Sim {0}", httpserver); + } + catch (WebException ex) + { + m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); + responseMap["connect"] = OSD.FromBoolean(false); + lock (m_blacklistedurls) + { + if (!m_blacklistedurls.ContainsKey(httpserver)) + m_blacklistedurls.Add(httpserver, System.Environment.TickCount); + } + + m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); + + return responseMap; + } + + string response_mapItems_reply = null; + { // get the response + try + { + WebResponse webResponse = mapitemsrequest.GetResponse(); + if (webResponse != null) + { + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + response_mapItems_reply = sr.ReadToEnd().Trim(); + } + else + { + return new OSDMap(); + } + } + catch (WebException) + { + responseMap["connect"] = OSD.FromBoolean(false); + lock (m_blacklistedurls) + { + if (!m_blacklistedurls.ContainsKey(httpserver)) + m_blacklistedurls.Add(httpserver, System.Environment.TickCount); + } + + m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); + + return responseMap; + } + OSD rezResponse = null; + try + { + rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply); + + responseMap = (OSDMap)rezResponse; + responseMap["requestID"] = OSD.FromUUID(requestID); + } + catch (Exception) + { + //m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message); + responseMap["connect"] = OSD.FromBoolean(false); + + return responseMap; + } + } + return responseMap; + } + + /// + /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates + /// + /// + /// + /// + /// + public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + { + List mapBlocks; + if ((flag & 0x10000) != 0) // user clicked on the map a tile that isn't visible + { + List response = new List(); + + // this should return one mapblock at most. But make sure: Look whether the one we requested is in there + mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); + if (mapBlocks != null) + { + foreach (MapBlockData block in mapBlocks) + { + if (block.X == minX && block.Y == minY) + { + // found it => add it to response + response.Add(block); + break; + } + } + } + + if (response.Count == 0) + { + // response still empty => couldn't find the map-tile the user clicked on => tell the client + MapBlockData block = new MapBlockData(); + block.X = (ushort)minX; + block.Y = (ushort)minY; + block.Access = 254; // == not there + response.Add(block); + } + remoteClient.SendMapBlock(response, 0); + } + else + { + // normal mapblock request. Use the provided values + mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, maxX + 4, maxY + 4); + remoteClient.SendMapBlock(mapBlocks, flag); + } + } + + public Hashtable OnHTTPGetMapImage(Hashtable keysvals) + { + m_log.Debug("[WORLD MAP]: Sending map image jpeg"); + Hashtable reply = new Hashtable(); + int statuscode = 200; + byte[] jpeg = new byte[0]; + + if (myMapImageJPEG.Length == 0) + { + MemoryStream imgstream = new MemoryStream(); + Bitmap mapTexture = new Bitmap(1,1); + ManagedImage managedImage; + Image image = (Image)mapTexture; + + try + { + // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data + + imgstream = new MemoryStream(); + + // non-async because we know we have the asset immediately. + AssetBase mapasset = m_scene.AssetCache.GetAsset(m_scene.RegionInfo.lastMapUUID, true); + + // Decode image to System.Drawing.Image + if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) + { + // Save to bitmap + mapTexture = new Bitmap(image); + + EncoderParameters myEncoderParameters = new EncoderParameters(); + myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); + + // Save bitmap to stream + mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters); + + // Write the stream to a byte array for output + jpeg = imgstream.ToArray(); + myMapImageJPEG = jpeg; + } + } + catch (Exception) + { + // Dummy! + m_log.Warn("[WORLD MAP]: Unable to generate Map image"); + } + finally + { + // Reclaim memory, these are unmanaged resources + mapTexture.Dispose(); + image.Dispose(); + imgstream.Close(); + imgstream.Dispose(); + } + } + else + { + // Use cached version so we don't have to loose our mind + jpeg = myMapImageJPEG; + } + + reply["str_response_string"] = Convert.ToBase64String(jpeg); + reply["int_response_code"] = statuscode; + reply["content_type"] = "image/jpeg"; + + return reply; + } + + // From msdn + private static ImageCodecInfo GetEncoderInfo(String mimeType) + { + ImageCodecInfo[] encoders; + encoders = ImageCodecInfo.GetImageEncoders(); + for (int j = 0; j < encoders.Length; ++j) + { + if (encoders[j].MimeType == mimeType) + return encoders[j]; + } + return null; + } + + public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) + { + uint xstart = 0; + uint ystart = 0; + + Utils.LongToUInts(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); + + OSDMap responsemap = new OSDMap(); + List avatars = m_scene.GetAvatars(); + OSDArray responsearr = new OSDArray(avatars.Count); + OSDMap responsemapdata = new OSDMap(); + int tc = System.Environment.TickCount; + /* + foreach (ScenePresence av in avatars) + { + responsemapdata = new OSDMap(); + responsemapdata["X"] = OSD.FromInteger((int)(xstart + av.AbsolutePosition.X)); + responsemapdata["Y"] = OSD.FromInteger((int)(ystart + av.AbsolutePosition.Y)); + responsemapdata["ID"] = OSD.FromUUID(UUID.Zero); + responsemapdata["Name"] = OSD.FromString("TH"); + responsemapdata["Extra"] = OSD.FromInteger(0); + responsemapdata["Extra2"] = OSD.FromInteger(0); + responsearr.Add(responsemapdata); + } + responsemap["1"] = responsearr; + */ + if (avatars.Count == 0) + { + responsemapdata = new OSDMap(); + responsemapdata["X"] = OSD.FromInteger((int)(xstart + 1)); + responsemapdata["Y"] = OSD.FromInteger((int)(ystart + 1)); + responsemapdata["ID"] = OSD.FromUUID(UUID.Zero); + responsemapdata["Name"] = OSD.FromString(Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString())); + responsemapdata["Extra"] = OSD.FromInteger(0); + responsemapdata["Extra2"] = OSD.FromInteger(0); + responsearr.Add(responsemapdata); + + responsemap["6"] = responsearr; + } + else + { + responsearr = new OSDArray(avatars.Count); + foreach (ScenePresence av in avatars) + { + responsemapdata = new OSDMap(); + responsemapdata["X"] = OSD.FromInteger((int)(xstart + av.AbsolutePosition.X)); + responsemapdata["Y"] = OSD.FromInteger((int)(ystart + av.AbsolutePosition.Y)); + responsemapdata["ID"] = OSD.FromUUID(UUID.Zero); + responsemapdata["Name"] = OSD.FromString(Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString())); + responsemapdata["Extra"] = OSD.FromInteger(1); + responsemapdata["Extra2"] = OSD.FromInteger(0); + responsearr.Add(responsemapdata); + } + responsemap["6"] = responsearr; + } + return responsemap; + } + + private void MakeRootAgent(ScenePresence avatar) + { + // You may ask, why this is in a threadpool to start with.. + // The reason is so we don't cause the thread to freeze waiting + // for the 1 second it costs to start a thread manually. + if (!threadrunning) + ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartThread)); + + lock (m_rootAgents) + { + if (!m_rootAgents.Contains(avatar.UUID)) + { + m_rootAgents.Add(avatar.UUID); + } + } + } + + private void MakeChildAgent(ScenePresence avatar) + { + List presences = m_scene.GetAvatars(); + int rootcount = 0; + for (int i = 0; i < presences.Count; i++) + { + if (presences[i] != null) + { + if (!presences[i].IsChildAgent) + rootcount++; + } + } + if (rootcount <= 1) + StopThread(); + + lock (m_rootAgents) + { + if (m_rootAgents.Contains(avatar.UUID)) + { + m_rootAgents.Remove(avatar.UUID); + } + } + } + } + + public struct MapRequestState + { + public UUID agentID; + public uint flags; + public uint EstateID; + public bool godlike; + public uint itemtype; + public ulong regionhandle; + } +} diff --git a/OpenSim/Region/DataSnapshot/LandSnapshot.cs b/OpenSim/Region/DataSnapshot/LandSnapshot.cs index bfc45fc..52659e4 100644 --- a/OpenSim/Region/DataSnapshot/LandSnapshot.cs +++ b/OpenSim/Region/DataSnapshot/LandSnapshot.cs @@ -34,7 +34,7 @@ using log4net; using OpenSim.Framework; using OpenSim.Region.DataSnapshot.Interfaces; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.World.Land; +using OpenSim.Region.CoreModules.World.Land; using OpenSim.Region.Framework.Scenes; using OpenMetaverse.Packets; using OpenSim.Framework.Communications.Cache; diff --git a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs index 6f7ff6b..949cc38 100644 --- a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs +++ b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs @@ -33,7 +33,7 @@ using log4net; using OpenSim.Region.DataSnapshot.Interfaces; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Land; +using OpenSim.Region.CoreModules.World.Land; using OpenSim.Framework; using OpenMetaverse; diff --git a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs deleted file mode 100644 index 1ac0807..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; - -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.AvatarFactory -{ - public class AvatarFactoryModule : IAvatarFactory, IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Scene m_scene = null; - private static readonly AvatarAppearance def = new AvatarAppearance(); - - public bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance appearance) - { - CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(avatarId); - //if ((profile != null) && (profile.RootFolder != null)) - if (profile != null) - { - appearance = m_scene.CommsManager.AvatarService.GetUserAppearance(avatarId); - if (appearance != null) - { - //SetAppearanceAssets(profile, ref appearance); - //m_log.DebugFormat("[APPEARANCE]: Found : {0}", appearance.ToString()); - return true; - } - } - - appearance = CreateDefault(avatarId); - m_log.ErrorFormat("[APPEARANCE]: Appearance not found for {0}, creating default", avatarId); - return false; - } - - private AvatarAppearance CreateDefault(UUID avatarId) - { - AvatarAppearance appearance = null; - AvatarWearable[] wearables; - byte[] visualParams; - GetDefaultAvatarAppearance(out wearables, out visualParams); - appearance = new AvatarAppearance(avatarId, wearables, visualParams); - - return appearance; - } - - public void Initialise(Scene scene, IConfigSource source) - { - scene.RegisterModuleInterface(this); - scene.EventManager.OnNewClient += NewClient; - - if (m_scene == null) - { - m_scene = scene; - } - - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "Default Avatar Factory"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void NewClient(IClientAPI client) - { - client.OnAvatarNowWearing += AvatarIsWearing; - } - - public void RemoveClient(IClientAPI client) - { - // client.OnAvatarNowWearing -= AvatarIsWearing; - } - - - public void SetAppearanceAssets(CachedUserInfo profile, ref AvatarAppearance appearance) - { - if (profile.RootFolder != null) - { - for (int i = 0; i < 13; i++) - { - if (appearance.Wearables[i].ItemID == UUID.Zero) - { - appearance.Wearables[i].AssetID = UUID.Zero; - } - else - { - InventoryItemBase baseItem = profile.RootFolder.FindItem(appearance.Wearables[i].ItemID); - - if (baseItem != null) - { - appearance.Wearables[i].AssetID = baseItem.AssetID; - } - else - { - m_log.ErrorFormat("[APPEARANCE]: Can't find inventory item {0}, setting to default", appearance.Wearables[i].ItemID); - appearance.Wearables[i].AssetID = def.Wearables[i].AssetID; - } - } - } - } - else - { - m_log.Error("[APPEARANCE]: you have no inventory, appearance stuff isn't going to work"); - } - } - - /// - /// Update what the avatar is wearing using an item from their inventory. - /// - /// - /// - public void AvatarIsWearing(Object sender, AvatarWearingArgs e) - { - IClientAPI clientView = (IClientAPI)sender; - ScenePresence avatar = m_scene.GetScenePresence(clientView.AgentId); - - if (avatar == null) - { - m_log.Error("[APPEARANCE]: Avatar is child agent, ignoring AvatarIsWearing event"); - return; - } - - CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId); - - AvatarAppearance avatAppearance = null; - if (!TryGetAvatarAppearance(clientView.AgentId, out avatAppearance)) - { - m_log.Warn("[APPEARANCE]: We didn't seem to find the appearance, falling back to ScenePresence"); - avatAppearance = avatar.Appearance; - } - - //m_log.DebugFormat("[APPEARANCE]: Received wearables for {0}", clientView.Name); - - if (profile != null) - { - if (profile.RootFolder != null) - { - foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) - { - if (wear.Type < 13) - { - avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; - } - } - - SetAppearanceAssets(profile, ref avatAppearance); - - m_scene.CommsManager.AvatarService.UpdateUserAppearance(clientView.AgentId, avatAppearance); - avatar.Appearance = avatAppearance; - } - else - { - m_log.WarnFormat( - "[APPEARANCE]: Inventory has not yet been received for {0}, cannot set wearables", - clientView.Name); - } - } - else - { - m_log.WarnFormat("[APPEARANCE]: Cannot set wearables for {0}, no user profile found", clientView.Name); - } - } - - public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) - { - visualParams = GetDefaultVisualParams(); - wearables = AvatarWearable.DefaultWearables; - } - - public void UpdateDatabase(UUID user, AvatarAppearance appearance) - { - m_scene.CommsManager.AvatarService.UpdateUserAppearance(user, appearance); - } - - private static byte[] GetDefaultVisualParams() - { - byte[] visualParams; - visualParams = new byte[218]; - for (int i = 0; i < 218; i++) - { - visualParams[i] = 100; - } - return visualParams; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs deleted file mode 100644 index dfa1caa..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - - // An instance of this class exists for each unique combination of - // IRC chat interface characteristics, as determined by the supplied - // configuration file. - - internal class ChannelState - { - - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static Regex arg = new Regex(@"\[[^\[\]]*\]"); - private static int _idk_ = 0; - private static int DEBUG_CHANNEL = 2147483647; - - // These are the IRC Connector configurable parameters with hard-wired - // default values (retained for compatability). - - internal string Server = null; - internal string Password = null; - internal string IrcChannel = null; - internal string BaseNickname = "OSimBot"; - internal uint Port = 6667; - internal string User = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot"; - - internal bool ClientReporting = true; - internal bool RelayChat = true; - internal bool RelayPrivateChannels = false; - internal int RelayChannel = 1; - internal List ValidInWorldChannels = new List(); - - // Connector agnostic parameters. These values are NOT shared with the - // connector and do not differentiate at an IRC level - - internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}"; - internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}"; - internal int RelayChannelOut = -1; - internal bool RandomizeNickname = true; - internal bool CommandsEnabled = false; - internal int CommandChannel = -1; - internal int ConnectDelay = 10; - internal int PingDelay = 15; - internal string DefaultZone = "Sim"; - - internal string _accessPassword = String.Empty; - internal Regex AccessPasswordRegex = null; - internal string AccessPassword - { - get { return _accessPassword; } - set - { - _accessPassword = value; - AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?[^,]+),\s*(?.+)$", _accessPassword), - RegexOptions.Compiled); - } - } - - - - // IRC connector reference - - internal IRCConnector irc = null; - - internal int idn = _idk_++; - - // List of regions dependent upon this connection - - internal List clientregions = new List(); - - // Needed by OpenChannel - - internal ChannelState() - { - } - - // This constructor is used by the Update* methods. A copy of the - // existing channel state is created, and distinguishing characteristics - // are copied across. - - internal ChannelState(ChannelState model) - { - Server = model.Server; - Password = model.Password; - IrcChannel = model.IrcChannel; - Port = model.Port; - BaseNickname = model.BaseNickname; - RandomizeNickname = model.RandomizeNickname; - User = model.User; - CommandsEnabled = model.CommandsEnabled; - CommandChannel = model.CommandChannel; - RelayChat = model.RelayChat; - RelayPrivateChannels = model.RelayPrivateChannels; - RelayChannelOut = model.RelayChannelOut; - RelayChannel = model.RelayChannel; - ValidInWorldChannels = model.ValidInWorldChannels; - PrivateMessageFormat = model.PrivateMessageFormat; - NoticeMessageFormat = model.NoticeMessageFormat; - ClientReporting = model.ClientReporting; - AccessPassword = model.AccessPassword; - DefaultZone = model.DefaultZone; - ConnectDelay = model.ConnectDelay; - PingDelay = model.PingDelay; - } - - // Read the configuration file, performing variable substitution and any - // necessary aliasing. See accompanying documentation for how this works. - // If you don't need variables, then this works exactly as before. - // If either channel or server are not specified, the request fails. - - internal static void OpenChannel(RegionState rs, IConfig config) - { - - // Create a new instance of a channel. This may not actually - // get used if an equivalent channel already exists. - - ChannelState cs = new ChannelState(); - - // Read in the configuration file and filter everything for variable - // subsititution. - - m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region); - - cs.Server = Substitute(rs, config.GetString("server", null)); - m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server); - cs.Password = Substitute(rs, config.GetString("password", null)); - // probably not a good idea to put a password in the log file - cs.IrcChannel = Substitute(rs, config.GetString("channel", null)); - m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel); - cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port)))); - m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port); - cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname)); - m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname); - cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname)))); - m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); - cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname)))); - m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); - cs.User = Substitute(rs, config.GetString("username", cs.User)); - m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User); - cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled)))); - m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled); - cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel)))); - m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); - cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel)))); - m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); - cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat)))); - m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat); - cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels)))); - m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); - cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels)))); - m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); - cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut)))); - m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut); - cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel)))); - m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); - cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel)))); - m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); - cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat)); - m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat); - cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat)); - m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat); - cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting?"1":"0"))) > 0; - m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); - cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting)))); - m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); - cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone)); - m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone); - cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay)))); - m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay); - cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay)))); - m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay); - cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword)); - m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword); - - - // Fail if fundamental information is still missing - - if (cs.Server == null || cs.IrcChannel == null || cs.BaseNickname == null || cs.User == null) - throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}", cs.idn, rs.Region)); - - m_log.InfoFormat("[IRC-Channel-{0}] Configuration for Region {1} is valid", cs.idn, rs.Region); - m_log.InfoFormat("[IRC-Channel-{0}] Server = {1}", cs.idn, cs.Server); - m_log.InfoFormat("[IRC-Channel-{0}] Channel = {1}", cs.idn, cs.IrcChannel); - m_log.InfoFormat("[IRC-Channel-{0}] Port = {1}", cs.idn, cs.Port); - m_log.InfoFormat("[IRC-Channel-{0}] Nickname = {1}", cs.idn, cs.BaseNickname); - m_log.InfoFormat("[IRC-Channel-{0}] User = {1}", cs.idn, cs.User); - - // Set the channel state for this region - - if (cs.RelayChat) - { - cs.ValidInWorldChannels.Add(0); - cs.ValidInWorldChannels.Add(DEBUG_CHANNEL); - } - - if (cs.RelayPrivateChannels) - cs.ValidInWorldChannels.Add(cs.RelayChannelOut); - - rs.cs = Integrate(rs, cs); - - } - - // An initialized channel state instance is passed in. If an identical - // channel state instance already exists, then the existing instance - // is used to replace the supplied value. - // If the instance matches with respect to IRC, then the underlying - // IRCConnector is assigned to the supplied channel state and the - // updated value is returned. - // If there is no match, then the supplied instance is completed by - // creating and assigning an instance of an IRC connector. - - private static ChannelState Integrate(RegionState rs, ChannelState p_cs) - { - - ChannelState cs = p_cs; - - // Check to see if we have an existing server/channel setup that can be used - // In the absence of variable substitution this will always resolve to the - // same ChannelState instance, and the table will only contains a single - // entry, so the performance considerations for the existing behavior are - // zero. Only the IRC connector is shared, the ChannelState still contains - // values that, while independent of the IRC connetion, do still distinguish - // this region's behavior. - - lock (IRCBridgeModule.m_channels) - { - - foreach (ChannelState xcs in IRCBridgeModule.m_channels) - { - if (cs.IsAPerfectMatchFor(xcs)) - { - m_log.DebugFormat("[IRC-Channel-{0}] Channel state matched", cs.idn); - cs = xcs; - break; - } - if (cs.IsAConnectionMatchFor(xcs)) - { - m_log.DebugFormat("[IRC-Channel-{0}] Channel matched", cs.idn); - cs.irc = xcs.irc; - break; - } - } - - } - - // No entry was found, so this is going to be a new entry. - - if (cs.irc == null) - { - - m_log.DebugFormat("[IRC-Channel-{0}] New channel required", cs.idn); - - if ((cs.irc = new IRCConnector(cs)) != null) - { - - IRCBridgeModule.m_channels.Add(cs); - - m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}", - cs.idn, rs.Region, cs.DefaultZone, - cs.CommandsEnabled ? "enabled" : "not enabled", - cs.RelayPrivateChannels ? "relayed" : "not relayed"); - } - else - { - string txt = String.Format("[IRC-Channel-{0}] Region {1} failed to connect to channel {2} on server {3}:{4}", - cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port); - m_log.Error(txt); - throw new Exception(txt); - } - } - else - { - m_log.InfoFormat("[IRC-Channel-{0}] Region {1} reusing existing connection to channel {2} on server {3}:{4}", - cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port); - } - - m_log.InfoFormat("[IRC-Channel-{0}] Region {1} associated with channel {2} on server {3}:{4}", - cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port); - - // We're finally ready to commit ourselves - - - return cs; - - } - - // These routines allow differentiating changes to - // the underlying channel state. If necessary, a - // new channel state will be created. - - internal ChannelState UpdateServer(RegionState rs, string server) - { - RemoveRegion(rs); - ChannelState cs = new ChannelState(this); - cs.Server = server; - cs = Integrate(rs, cs); - cs.AddRegion(rs); - return cs; - } - - internal ChannelState UpdatePort(RegionState rs, string port) - { - RemoveRegion(rs); - ChannelState cs = new ChannelState(this); - cs.Port = Convert.ToUInt32(port); - cs = Integrate(rs, cs); - cs.AddRegion(rs); - return cs; - } - - internal ChannelState UpdateChannel(RegionState rs, string channel) - { - RemoveRegion(rs); - ChannelState cs = new ChannelState(this); - cs.IrcChannel = channel; - cs = Integrate(rs, cs); - cs.AddRegion(rs); - return cs; - } - - internal ChannelState UpdateNickname(RegionState rs, string nickname) - { - RemoveRegion(rs); - ChannelState cs = new ChannelState(this); - cs.BaseNickname = nickname; - cs = Integrate(rs, cs); - cs.AddRegion(rs); - return cs; - } - - internal ChannelState UpdateClientReporting(RegionState rs, string cr) - { - RemoveRegion(rs); - ChannelState cs = new ChannelState(this); - cs.ClientReporting = Convert.ToBoolean(cr); - cs = Integrate(rs, cs); - cs.AddRegion(rs); - return cs; - } - - internal ChannelState UpdateRelayIn(RegionState rs, string channel) - { - RemoveRegion(rs); - ChannelState cs = new ChannelState(this); - cs.RelayChannel = Convert.ToInt32(channel); - cs = Integrate(rs, cs); - cs.AddRegion(rs); - return cs; - } - - internal ChannelState UpdateRelayOut(RegionState rs, string channel) - { - RemoveRegion(rs); - ChannelState cs = new ChannelState(this); - cs.RelayChannelOut = Convert.ToInt32(channel); - cs = Integrate(rs, cs); - cs.AddRegion(rs); - return cs; - } - - // Determine whether or not this is a 'new' channel. Only those - // attributes that uniquely distinguish an IRC connection should - // be included here (and only those attributes should really be - // in the ChannelState structure) - - private bool IsAConnectionMatchFor(ChannelState cs) - { - return ( - Server == cs.Server && - IrcChannel == cs.IrcChannel && - Port == cs.Port && - BaseNickname == cs.BaseNickname && - User == cs.User - ); - } - - // This level of obsessive matching allows us to produce - // a minimal overhead int he case of a server which does - // need to differentiate IRC at a region level. - - private bool IsAPerfectMatchFor(ChannelState cs) - { - return ( IsAConnectionMatchFor(cs) && - RelayChannelOut == cs.RelayChannelOut && - PrivateMessageFormat == cs.PrivateMessageFormat && - NoticeMessageFormat == cs.NoticeMessageFormat && - RandomizeNickname == cs.RandomizeNickname && - AccessPassword == cs.AccessPassword && - CommandsEnabled == cs.CommandsEnabled && - CommandChannel == cs.CommandChannel && - DefaultZone == cs.DefaultZone && - RelayPrivateChannels == cs.RelayPrivateChannels && - RelayChannel == cs.RelayChannel && - RelayChat == cs.RelayChat && - ClientReporting == cs.ClientReporting - ); - } - - // This function implements the variable substitution mechanism - // for the configuration values. Each string read from the - // configuration file is scanned for '[...]' enclosures. Each - // one that is found is replaced by either a runtime variable - // (%xxx) or an existing configuration key. When no further - // substitution is possible, the remaining string is returned - // to the caller. This allows for arbitrarily nested - // enclosures. - - private static string Substitute(RegionState rs, string instr) - { - - string result = instr; - - if (result == null || result.Length == 0) - return result; - - // Repeatedly scan the string until all possible - // substitutions have been performed. - - // m_log.DebugFormat("[IRC-Channel] Parse[1]: {0}", result); - - while (arg.IsMatch(result)) - { - - string vvar = arg.Match(result).ToString(); - string var = vvar.Substring(1,vvar.Length-2).Trim(); - - switch (var.ToLower()) - { - case "%region" : - result = result.Replace(vvar, rs.Region); - break; - case "%host" : - result = result.Replace(vvar, rs.Host); - break; - case "%master1" : - result = result.Replace(vvar, rs.MA1); - break; - case "%master2" : - result = result.Replace(vvar, rs.MA2); - break; - case "%locx" : - result = result.Replace(vvar, rs.LocX); - break; - case "%locy" : - result = result.Replace(vvar, rs.LocY); - break; - case "%k" : - result = result.Replace(vvar, rs.IDK); - break; - default : - result = result.Replace(vvar, rs.config.GetString(var,var)); - break; - } - // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result); - } - - // m_log.DebugFormat("[IRC-Channel] Parse[3]: {0}", result); - return result; - - } - - public void Close() - { - m_log.InfoFormat("[IRC-Channel-{0}] Closing channel <{1}> to server <{2}:{3}>", - idn, IrcChannel, Server, Port); - m_log.InfoFormat("[IRC-Channel-{0}] There are {1} active clients", - idn, clientregions.Count); - irc.Close(); - } - - public void Open() - { - m_log.InfoFormat("[IRC-Channel-{0}] Opening channel <{1}> to server <{2}:{3}>", - idn, IrcChannel, Server, Port); - - irc.Open(); - - } - - // These are called by each region that attaches to this channel. The call affects - // only the relationship of the region with the channel. Not the channel to IRC - // relationship (unless it is closed and we want it open). - - public void Open(RegionState rs) - { - AddRegion(rs); - Open(); - } - - // Close is called to ensure that the IRC session is terminated if this is the - // only client. - - public void Close(RegionState rs) - { - RemoveRegion(rs); - lock (IRCBridgeModule.m_channels) - { - if (clientregions.Count == 0) - { - Close(); - IRCBridgeModule.m_channels.Remove(this); - m_log.InfoFormat("[IRC-Channel-{0}] Region {1} is last user of channel <{2}> to server <{3}:{4}>", - idn, rs.Region, IrcChannel, Server, Port); - m_log.InfoFormat("[IRC-Channel-{0}] Removed", idn); - } - } - } - - // Add a client region to this channel if it is not already known - - public void AddRegion(RegionState rs) - { - m_log.InfoFormat("[IRC-Channel-{0}] Adding region {1} to channel <{2}> to server <{3}:{4}>", - idn, rs.Region, IrcChannel, Server, Port); - if (!clientregions.Contains(rs)) - { - clientregions.Add(rs); - lock (irc) irc.depends++; - } - } - - // Remove a client region from the channel. If this is the last - // region, then clean up the channel. The connector will clean itself - // up if it finds itself about to be GC'd. - - public void RemoveRegion(RegionState rs) - { - - m_log.InfoFormat("[IRC-Channel-{0}] Removing region {1} from channel <{2} to server <{3}:{4}>", - idn, rs.Region, IrcChannel, Server, Port); - - if (clientregions.Contains(rs)) - { - clientregions.Remove(rs); - lock (irc) irc.depends--; - } - - } - - // This function is lifted from the IRCConnector because it - // contains information that is not differentiating from an - // IRC point-of-view. - - public static void OSChat(IRCConnector p_irc, OSChatMessage c, bool cmsg) - { - - // m_log.DebugFormat("[IRC-OSCHAT] from {0}:{1}", p_irc.Server, p_irc.IrcChannel); - - try - { - - // Scan through the set of unique channel configuration for those - // that belong to this connector. And then forward the message to - // all regions known to those channels. - // Note that this code is responsible for completing some of the - // settings for the inbound OSChatMessage - - lock (IRCBridgeModule.m_channels) - { - foreach (ChannelState cs in IRCBridgeModule.m_channels) - { - if ( p_irc == cs.irc) - { - - // This non-IRC differentiator moved to here - - if (cmsg && !cs.ClientReporting) - continue; - - // This non-IRC differentiator moved to here - - c.Channel = (cs.RelayPrivateChannels ? cs.RelayChannel : 0); - - foreach (RegionState region in cs.clientregions) - { - region.OSChat(cs.irc, c); - } - - } - } - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-OSCHAT]: BroadcastSim Exception: {0}", ex.Message); - m_log.Debug(ex); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs deleted file mode 100644 index f234b75..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Sockets; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - public class ChatModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const int DEBUG_CHANNEL = 2147483647; - - private bool m_enabled = true; - private int m_saydistance = 30; - private int m_shoutdistance = 100; - private int m_whisperdistance = 10; - private List m_scenes = new List(); - - internal object m_syncInit = new object(); - - #region IRegionModule Members - public virtual void Initialise(Scene scene, IConfigSource config) - { - // wrap this in a try block so that defaults will work if - // the config file doesn't specify otherwise. - try - { - m_enabled = config.Configs["Chat"].GetBoolean("enabled", m_enabled); - if (!m_enabled) return; - - m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); - m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); - m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); - } - catch (Exception) - { - } - - lock (m_syncInit) - { - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnChatFromWorld += OnChatFromWorld; - scene.EventManager.OnChatBroadcast += OnChatBroadcast; - } - } - - m_log.InfoFormat("[CHAT] initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, - m_whisperdistance, m_saydistance, m_shoutdistance); - } - public virtual void PostInitialise() - { - } - - public virtual void Close() - { - } - - public virtual string Name - { - get { return "ChatModule"; } - } - - public virtual bool IsSharedModule - { - get { return true; } - } - - #endregion - - - public virtual void OnNewClient(IClientAPI client) - { - client.OnChatFromClient += OnChatFromClient; - } - - protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c) - { - ScenePresence avatar; - Scene scene = (Scene)c.Scene; - if ((avatar = scene.GetScenePresence(c.Sender.AgentId)) != null) - c.Position = avatar.AbsolutePosition; - - return c; - } - - public virtual void OnChatFromClient(Object sender, OSChatMessage c) - { - c = FixPositionOfChatMessage(c); - - // redistribute to interested subscribers - Scene scene = (Scene)c.Scene; - scene.EventManager.TriggerOnChatFromClient(sender, c); - - // early return if not on public or debug channel - if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; - - // sanity check: - if (c.Sender == null) - { - m_log.ErrorFormat("[CHAT] OnChatFromClient from {0} has empty Sender field!", sender); - return; - } - - DeliverChatToAvatars(ChatSourceType.Agent, c); - } - - public virtual void OnChatFromWorld(Object sender, OSChatMessage c) - { - // early return if not on public or debug channel - if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; - - DeliverChatToAvatars(ChatSourceType.Object, c); - } - - protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) - { - string fromName = c.From; - UUID fromID = UUID.Zero; - string message = c.Message; - IScene scene = c.Scene; - Vector3 fromPos = c.Position; - Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, - scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); - - if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; - - switch (sourceType) - { - case ChatSourceType.Agent: - if (!(scene is Scene)) - { - m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}", - scene.RegionInfo.RegionName, c.Sender.AgentId); - return; - } - ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId); - fromPos = avatar.AbsolutePosition; - fromName = avatar.Name; - fromID = c.Sender.AgentId; - - break; - - case ChatSourceType.Object: - fromID = c.SenderUUID; - - break; - } - - // TODO: iterate over message - if (message.Length >= 1000) // libomv limit - message = message.Substring(0, 1000); - - // m_log.DebugFormat("[CHAT]: DCTA: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, c.Type, sourceType); - - foreach (Scene s in m_scenes) - { - s.ForEachScenePresence(delegate(ScenePresence presence) - { - TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, - c.Type, message, sourceType); - }); - } - } - - - static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); - public virtual void OnChatBroadcast(Object sender, OSChatMessage c) - { - // unless the chat to be broadcast is of type Region, we - // drop it if its channel is neither 0 nor DEBUG_CHANNEL - if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL && c.Type != ChatTypeEnum.Region) return; - - ChatTypeEnum cType = c.Type; - if (c.Channel == DEBUG_CHANNEL) - cType = ChatTypeEnum.DebugChannel; - - if (cType == ChatTypeEnum.Region) - cType = ChatTypeEnum.Say; - - if (c.Message.Length > 1100) - c.Message = c.Message.Substring(0, 1000); - - // broadcast chat works by redistributing every incoming chat - // message to each avatar in the scene. - string fromName = c.From; - - UUID fromID = UUID.Zero; - ChatSourceType sourceType = ChatSourceType.Object; - if (null != c.Sender) - { - ScenePresence avatar = (c.Scene as Scene).GetScenePresence(c.Sender.AgentId); - fromID = c.Sender.AgentId; - fromName = avatar.Name; - sourceType = ChatSourceType.Agent; - } - - // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); - - ((Scene)c.Scene).ForEachScenePresence( - delegate(ScenePresence presence) - { - // ignore chat from child agents - if (presence.IsChildAgent) return; - - IClientAPI client = presence.ControllingClient; - - // don't forward SayOwner chat from objects to - // non-owner agents - if ((c.Type == ChatTypeEnum.Owner) && - (null != c.SenderObject) && - (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) - return; - - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, - (byte)sourceType, (byte)ChatAudibleLevel.Fully); - }); - } - - - protected virtual void TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, - UUID fromAgentID, string fromName, ChatTypeEnum type, - string message, ChatSourceType src) - { - // don't send stuff to child agents - if (presence.IsChildAgent) return; - - Vector3 fromRegionPos = fromPos + regionPos; - Vector3 toRegionPos = presence.AbsolutePosition + - new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, - presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); - - int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos)); - - if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || - type == ChatTypeEnum.Say && dis > m_saydistance || - type == ChatTypeEnum.Shout && dis > m_shoutdistance) - { - return; - } - - // TODO: should change so the message is sent through the avatar rather than direct to the ClientView - presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, - fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs deleted file mode 100644 index ccd81c7..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - public class IRCBridgeModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - internal static bool configured = false; - internal static bool enabled = false; - internal static IConfig m_config = null; - - internal static List m_channels = new List(); - internal static List m_regions = new List(); - - internal static string password = String.Empty; - - internal RegionState region = null; - - #region IRegionModule Members - - public string Name - { - get { return "IRCBridgeModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void Initialise(Scene scene, IConfigSource config) - { - // Do a once-only scan of the configuration file to make - // sure it's basically intact. - - if (!configured) - { - configured = true; - - try - { - if ((m_config = config.Configs["IRC"]) == null) - { - m_log.InfoFormat("[IRC-Bridge] module not configured"); - return; - } - - if (!m_config.GetBoolean("enabled", false)) - { - m_log.InfoFormat("[IRC-Bridge] module disabled in configuration"); - return; - } - } - catch (Exception e) - { - m_log.ErrorFormat("[IRC-Bridge] configuration failed : {0}", e.Message); - return; - } - - enabled = true; - - if (config.Configs["RemoteAdmin"] != null) - { - password = config.Configs["RemoteAdmin"].GetString("access_password", password); - scene.CommsManager.HttpServer.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false); - } - } - - // Iff the IRC bridge is enabled, then each new region may be - // connected to IRC. But it should NOT be obligatory (and it - // is not). - // We have to do ALL of the startup here because PostInitialize - // is not called when a region gets created in-flight from the - // command line. - - if (enabled) - { - try - { - m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName); - region = new RegionState(scene, m_config); - lock (m_regions) m_regions.Add(region); - region.Open(); - } - catch (Exception e) - { - m_log.WarnFormat("[IRC-Bridge] Region {0} not connected to IRC : {1}", scene.RegionInfo.RegionName, e.Message); - m_log.Debug(e); - } - } - else - { - m_log.WarnFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName); - } - } - - // This module can be called in-flight in which case PostInitialize - // is not called following Initialize. So no use is made of this - // call. - - public void PostInitialise() - { - } - - // Called immediately before the region module is unloaded. Cleanup - // the region. - - public void Close() - { - if (!enabled) - return; - - region.Close(); - lock (m_regions) m_regions.Remove(region); - } - - #endregion - - public static XmlRpcResponse XmlRpcAdminMethod(XmlRpcRequest request) - { - m_log.Info("[IRC-Bridge]: XML RPC Admin Entry"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - Hashtable requestData = (Hashtable)request.Params[0]; - bool found = false; - string region = String.Empty; - - if (password != String.Empty) - { - if (!requestData.ContainsKey("password")) - throw new Exception("Invalid request"); - if ((string)requestData["password"] != password) - throw new Exception("Invalid request"); - } - - if (!requestData.ContainsKey("region")) - throw new Exception("No region name specified"); - region = (string)requestData["region"]; - - foreach (RegionState rs in m_regions) - { - if (rs.Region == region) - { - responseData["server"] = rs.cs.Server; - responseData["port"] = (int)rs.cs.Port; - responseData["user"] = rs.cs.User; - responseData["channel"] = rs.cs.IrcChannel; - responseData["enabled"] = rs.cs.irc.Enabled; - responseData["connected"] = rs.cs.irc.Connected; - responseData["nickname"] = rs.cs.irc.Nick; - found = true; - break; - } - } - - if (!found) throw new Exception(String.Format("Region <{0}> not found", region)); - - responseData["success"] = true; - } - catch (Exception e) - { - m_log.InfoFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message); - - responseData["success"] = "false"; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; - } - - m_log.Debug("[IRC-Bridge]: XML RPC Admin Exit"); - - return response; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs deleted file mode 100644 index c3cafb0..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs +++ /dev/null @@ -1,887 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Timers; -using System.Collections.Generic; -using System.IO; -using System.Net.Sockets; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - public class IRCConnector - { - - #region Global (static) state - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // Local constants - - private static readonly Vector3 CenterOfRegion = new Vector3(128, 128, 20); - private static readonly char[] CS_SPACE = { ' ' }; - - private const int WD_INTERVAL = 1000; // base watchdog interval - private static int PING_PERIOD = 15; // WD intervals per PING - private static int ICCD_PERIOD = 10; // WD intervals between Connects - private static int L_TIMEOUT = 25; // Login time out interval - - private static int _idk_ = 0; // core connector identifier - private static int _pdk_ = 0; // ping interval counter - private static int _icc_ = 0; // IRC connect counter - - // List of configured connectors - - private static List m_connectors = new List(); - - // Watchdog state - - private static System.Timers.Timer m_watchdog = null; - - static IRCConnector() - { - m_log.DebugFormat("[IRC-Connector]: Static initialization started"); - m_watchdog = new System.Timers.Timer(WD_INTERVAL); - m_watchdog.Elapsed += new ElapsedEventHandler(WatchdogHandler); - m_watchdog.AutoReset = true; - m_watchdog.Start(); - m_log.DebugFormat("[IRC-Connector]: Static initialization complete"); - } - - #endregion - - #region Instance state - - // Connector identity - - internal int idn = _idk_++; - - // How many regions depend upon this connection - // This count is updated by the ChannelState object and reflects the sum - // of the region clients associated with the set of associated channel - // state instances. That's why it cannot be managed here. - - internal int depends = 0; - - // Working threads - - private Thread m_listener = null; - - private Object msyncConnect = new Object(); - - internal bool m_randomizeNick = true; // add random suffix - internal string m_baseNick = null; // base name for randomizing - internal string m_nick = null; // effective nickname - - public string Nick // Public property - { - get { return m_nick; } - set { m_nick = value; } - } - - private bool m_enabled = false; // connector enablement - public bool Enabled - { - get { return m_enabled; } - } - - private bool m_connected = false; // connection status - private bool m_pending = false; // login disposition - private int m_timeout = L_TIMEOUT; // login timeout counter - public bool Connected - { - get { return m_connected; } - } - - private string m_ircChannel; // associated channel id - public string IrcChannel - { - get { return m_ircChannel; } - set { m_ircChannel = value; } - } - - private uint m_port = 6667; // session port - public uint Port - { - get { return m_port; } - set { m_port = value; } - } - - private string m_server = null; // IRC server name - public string Server - { - get { return m_server; } - set { m_server = value; } - } - private string m_password = null; - public string Password - { - get { return m_password; } - set { m_password = value; } - } - - private string m_user = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot"; - public string User - { - get { return m_user; } - } - - // Network interface - - private TcpClient m_tcp; - private NetworkStream m_stream = null; - private StreamReader m_reader; - private StreamWriter m_writer; - - // Channel characteristic info (if available) - - internal string usermod = String.Empty; - internal string chanmod = String.Empty; - internal string version = String.Empty; - internal bool motd = false; - - #endregion - - #region connector instance management - - internal IRCConnector(ChannelState cs) - { - - // Prepare network interface - - m_tcp = null; - m_writer = null; - m_reader = null; - - // Setup IRC session parameters - - m_server = cs.Server; - m_password = cs.Password; - m_baseNick = cs.BaseNickname; - m_randomizeNick = cs.RandomizeNickname; - m_ircChannel = cs.IrcChannel; - m_port = cs.Port; - m_user = cs.User; - - if (m_watchdog == null) - { - // Non-differentiating - - ICCD_PERIOD = cs.ConnectDelay; - PING_PERIOD = cs.PingDelay; - - // Smaller values are not reasonable - - if (ICCD_PERIOD < 5) - ICCD_PERIOD = 5; - - if (PING_PERIOD < 5) - PING_PERIOD = 5; - - _icc_ = ICCD_PERIOD; // get started right away! - - } - - // The last line of defense - - if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) - throw new Exception("Invalid connector configuration"); - - // Generate an initial nickname if randomizing is enabled - - if (m_randomizeNick) - { - m_nick = m_baseNick + Util.RandomClass.Next(1, 99); - } - - // Add the newly created connector to the known connectors list - - m_connectors.Add(this); - - m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); - - } - - ~IRCConnector() - { - m_watchdog.Stop(); - Close(); - } - - // Mark the connector as connectable. Harmless if already enabled. - - public void Open() - { - if (!m_enabled) - { - - m_connectors.Add(this); - m_enabled = true; - - if (!Connected) - { - Connect(); - } - - } - } - - // Only close the connector if the dependency count is zero. - - public void Close() - { - - m_log.InfoFormat("[IRC-Connector-{0}] Closing", idn); - - lock (msyncConnect) - { - - if ((depends == 0) && Enabled) - { - - m_enabled = false; - - if (Connected) - { - m_log.DebugFormat("[IRC-Connector-{0}] Closing interface", idn); - - // Cleanup the IRC session - - try - { - m_writer.WriteLine(String.Format("QUIT :{0} to {1} wormhole to {2} closing", - m_nick, m_ircChannel, m_server)); - m_writer.Flush(); - } - catch (Exception) {} - - - m_connected = false; - - try { m_writer.Close(); } catch (Exception) {} - try { m_reader.Close(); } catch (Exception) {} - try { m_stream.Close(); } catch (Exception) {} - try { m_tcp.Close(); } catch (Exception) {} - - } - - m_connectors.Remove(this); - - } - } - - m_log.InfoFormat("[IRC-Connector-{0}] Closed", idn); - - } - - #endregion - - #region session management - - // Connect to the IRC server. A connector should always be connected, once enabled - - public void Connect() - { - - if (!m_enabled) - return; - - // Delay until next WD cycle if this is too close to the last start attempt - - while (_icc_ < ICCD_PERIOD) - return; - - m_log.DebugFormat("[IRC-Connector-{0}]: Connection request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel); - - lock (msyncConnect) - { - - _icc_ = 0; - - try - { - if (m_connected) return; - - m_connected = true; - m_pending = true; - m_timeout = L_TIMEOUT; - - m_tcp = new TcpClient(m_server, (int)m_port); - m_stream = m_tcp.GetStream(); - m_reader = new StreamReader(m_stream); - m_writer = new StreamWriter(m_stream); - - m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port); - - m_listener = new Thread(new ThreadStart(ListenerRun)); - m_listener.Name = "IRCConnectorListenerThread"; - m_listener.IsBackground = true; - m_listener.Start(); - ThreadTracker.Add(m_listener); - - // This is the message order recommended by RFC 2812 - if (m_password != null) - m_writer.WriteLine(String.Format("PASS {0}", m_password)); - m_writer.WriteLine(String.Format("NICK {0}", m_nick)); - m_writer.Flush(); - m_writer.WriteLine(m_user); - m_writer.Flush(); - m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); - m_writer.Flush(); - - m_log.InfoFormat("[IRC-Connector-{0}]: {1} has asked to join {2}", idn, m_nick, m_ircChannel); - - } - catch (Exception e) - { - m_log.ErrorFormat("[IRC-Connector-{0}] cannot connect {1} to {2}:{3}: {4}", - idn, m_nick, m_server, m_port, e.Message); - m_connected = false; - m_pending = false; - } - - } - - return; - - } - - // Reconnect is used to force a re-cycle of the IRC connection. Should generally - // be a transparent event - - public void Reconnect() - { - m_log.DebugFormat("[IRC-Connector-{0}]: Reconnect request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel); - - // Don't do this if a Connect is in progress... - - lock (msyncConnect) - { - - if (m_connected) - { - m_log.InfoFormat("[IRC-Connector-{0}] Resetting connector", idn); - - // Mark as disconnected. This will allow the listener thread - // to exit if still in-flight. - - - // The listener thread is not aborted - it *might* actually be - // the thread that is running the Reconnect! Instead just close - // the socket and it will disappear of its own accord, once this - // processing is completed. - - try { m_writer.Close(); } catch (Exception) {} - try { m_reader.Close(); } catch (Exception) {} - try { m_tcp.Close(); } catch (Exception) {} - - m_connected = false; - m_pending = false; - - } - - } - - Connect(); - - } - - #endregion - - #region Outbound (to-IRC) message handlers - - public void PrivMsg(string pattern, string from, string region, string msg) - { - - m_log.DebugFormat("[IRC-Connector-{0}] PrivMsg to IRC from {1}: <{2}>", idn, from, - String.Format(pattern, m_ircChannel, from, region, msg)); - - // One message to the IRC server - - try - { - m_writer.WriteLine(pattern, m_ircChannel, from, region, msg); - m_writer.Flush(); - m_log.DebugFormat("[IRC-Connector-{0}]: PrivMsg from {1} in {2}: {3}", idn, from, region, msg); - } - catch (IOException) - { - m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg I/O Error: disconnected from IRC server", idn); - Reconnect(); - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg exception : {1}", idn, ex.Message); - m_log.Debug(ex); - } - - } - - public void Send(string msg) - { - - m_log.DebugFormat("[IRC-Connector-{0}] Send to IRC : <{1}>", idn, msg); - - try - { - m_writer.WriteLine(msg); - m_writer.Flush(); - m_log.DebugFormat("[IRC-Connector-{0}] Sent command string: {1}", idn, msg); - } - catch (IOException) - { - m_log.ErrorFormat("[IRC-Connector-{0}] Disconnected from IRC server.(Send)", idn); - Reconnect(); - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Connector-{0}] Send exception trap: {0}", idn, ex.Message); - m_log.Debug(ex); - } - - } - - #endregion - - public void ListenerRun() - { - string inputLine; - - try - { - while (m_enabled && m_connected) - { - - if ((inputLine = m_reader.ReadLine()) == null) - throw new Exception("Listener input socket closed"); - - // m_log.Info("[IRCConnector]: " + inputLine); - - if (inputLine.Contains("PRIVMSG")) - { - - Dictionary data = ExtractMsg(inputLine); - - // Any chat ??? - if (data != null) - { - - OSChatMessage c = new OSChatMessage(); - c.Message = data["msg"]; - c.Type = ChatTypeEnum.Region; - c.Position = CenterOfRegion; - c.From = data["nick"]; - c.Sender = null; - c.SenderUUID = UUID.Zero; - - // Is message "\001ACTION foo bar\001"? - // Then change to: "/me foo bar" - - if ((1 == c.Message[0]) && c.Message.Substring(1).StartsWith("ACTION")) - c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9)); - - ChannelState.OSChat(this, c, false); - - } - - } - else - { - ProcessIRCCommand(inputLine); - } - } - } - catch (Exception /*e*/) - { - // m_log.ErrorFormat("[IRC-Connector-{0}]: ListenerRun exception trap: {1}", idn, e.Message); - // m_log.Debug(e); - } - - // This is potentially circular, but harmless if so. - // The connection is marked as not connected the first time - // through reconnect. - - if (m_enabled) Reconnect(); - - } - - private Regex RE = new Regex(@":(?[\w-]*)!(?\S*) PRIVMSG (?\S+) :(?.*)", - RegexOptions.Multiline); - - private Dictionary ExtractMsg(string input) - { - //examines IRC commands and extracts any private messages - // which will then be reboadcast in the Sim - - // m_log.InfoFormat("[IRC-Connector-{0}]: ExtractMsg: {1}", idn, input); - - Dictionary result = null; - MatchCollection matches = RE.Matches(input); - - // Get some direct matches $1 $4 is a - if ((matches.Count == 0) || (matches.Count != 1) || (matches[0].Groups.Count != 5)) - { - // m_log.Info("[IRCConnector]: Number of matches: " + matches.Count); - // if (matches.Count > 0) - // { - // m_log.Info("[IRCConnector]: Number of groups: " + matches[0].Groups.Count); - // } - return null; - } - - result = new Dictionary(); - result.Add("nick", matches[0].Groups[1].Value); - result.Add("user", matches[0].Groups[2].Value); - result.Add("channel", matches[0].Groups[3].Value); - result.Add("msg", matches[0].Groups[4].Value); - - return result; - } - - public void BroadcastSim(string sender, string format, params string[] args) - { - try - { - OSChatMessage c = new OSChatMessage(); - c.From = sender; - c.Message = String.Format(format, args); - c.Type = ChatTypeEnum.Region; // ChatTypeEnum.Say; - c.Position = CenterOfRegion; - c.Sender = null; - c.SenderUUID = UUID.Zero; - - ChannelState.OSChat(this, c, true); - - } - catch (Exception ex) // IRC gate should not crash Sim - { - m_log.ErrorFormat("[IRC-Connector-{0}]: BroadcastSim Exception Trap: {1}\n{2}", idn, ex.Message, ex.StackTrace); - } - } - - #region IRC Command Handlers - - public void ProcessIRCCommand(string command) - { - - string[] commArgs; - string c_server = m_server; - - string pfx = String.Empty; - string cmd = String.Empty; - string parms = String.Empty; - - // ":" indicates that a prefix is present - // There are NEVER more than 17 real - // fields. A parameter that starts with - // ":" indicates that the remainder of the - // line is a single parameter value. - - commArgs = command.Split(CS_SPACE,2); - - if (commArgs[0].StartsWith(":")) - { - pfx = commArgs[0].Substring(1); - commArgs = commArgs[1].Split(CS_SPACE,2); - } - - cmd = commArgs[0]; - parms = commArgs[1]; - - // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd); - - switch (cmd) - { - - // Messages 001-004 are always sent - // following signon. - - case "001" : // Welcome ... - case "002" : // Server information - case "003" : // Welcome ... - break; - case "004" : // Server information - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - commArgs = parms.Split(CS_SPACE); - c_server = commArgs[1]; - m_server = c_server; - version = commArgs[2]; - usermod = commArgs[3]; - chanmod = commArgs[4]; - break; - case "005" : // Server information - break; - case "042" : - case "250" : - case "251" : - case "252" : - case "254" : - case "255" : - case "265" : - case "266" : - case "332" : // Subject - case "333" : // Subject owner (?) - case "353" : // Name list - case "366" : // End-of-Name list marker - case "372" : // MOTD body - case "375" : // MOTD start - m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); - break; - case "376" : // MOTD end - m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); - motd = true; - break; - case "451" : // Not registered - break; - case "433" : // Nickname in use - // Gen a new name - m_nick = m_baseNick + Util.RandomClass.Next(1, 99); - m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick); - // Retry - m_writer.WriteLine(String.Format("NICK {0}", m_nick)); - m_writer.Flush(); - m_writer.WriteLine(m_user); - m_writer.Flush(); - m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); - m_writer.Flush(); - break; - case "479" : // Bad channel name, etc. This will never work, so disable the connection - m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); - m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd); - m_enabled = false; - m_connected = false; - m_pending = false; - break; - case "NOTICE" : - m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); - break; - case "ERROR" : - m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); - if (parms.Contains("reconnect too fast")) - ICCD_PERIOD++; - m_pending = false; - Reconnect(); - break; - case "PING" : - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - m_writer.WriteLine(String.Format("PONG {0}", parms)); - m_writer.Flush(); - break; - case "PONG" : - break; - case "JOIN": - if (m_pending) - { - m_log.InfoFormat("[IRC-Connector-{0}] [{1}] Connected", idn, cmd); - m_pending = false; - } - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcJoin(pfx, cmd, parms); - break; - case "PART": - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcPart(pfx, cmd, parms); - break; - case "MODE": - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcMode(pfx, cmd, parms); - break; - case "NICK": - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcNickChange(pfx, cmd, parms); - break; - case "KICK": - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcKick(pfx, cmd, parms); - break; - case "QUIT": - m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcQuit(pfx, cmd, parms); - break; - default : - m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms); - break; - } - - // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd); - - } - - public void eventIrcJoin(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string IrcUser = prefix.Split('!')[0]; - string IrcChannel = args[0]; - - if (IrcChannel.StartsWith(":")) - IrcChannel = IrcChannel.Substring(1); - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCJoin {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(IrcUser, "/me joins {0}", IrcChannel); - } - - public void eventIrcPart(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string IrcUser = prefix.Split('!')[0]; - string IrcChannel = args[0]; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(IrcUser, "/me parts {0}", IrcChannel); - } - - public void eventIrcMode(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string UserMode = args[1]; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel); - if (UserMode.Substring(0, 1) == ":") - { - UserMode = UserMode.Remove(0, 1); - } - } - - public void eventIrcNickChange(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string UserOldNick = prefix.Split('!')[0]; - string UserNewNick = args[0].Remove(0, 1); - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCNickChange {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(UserOldNick, "/me is now known as {0}", UserNewNick); - } - - public void eventIrcKick(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,3); - string UserKicker = prefix.Split('!')[0]; - string IrcChannel = args[0]; - string UserKicked = args[1]; - string KickMessage = args[2]; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage); - - if (UserKicked == m_nick) - { - BroadcastSim(m_nick, "Hey, that was me!!!"); - } - - } - - public void eventIrcQuit(string prefix, string command, string parms) - { - string IrcUser = prefix.Split('!')[0]; - string QuitMessage = parms; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(IrcUser, "/me quits saying \"{0}\"", QuitMessage); - } - - #endregion - - #region Connector Watch Dog - - // A single watch dog monitors extant connectors and makes sure that they - // are re-connected as necessary. If a connector IS connected, then it is - // pinged, but only if a PING period has elapsed. - - protected static void WatchdogHandler(Object source, ElapsedEventArgs args) - { - - // m_log.InfoFormat("[IRC-Watchdog] Status scan"); - - _pdk_ = (_pdk_+1)%PING_PERIOD; // cycle the ping trigger - _icc_++; // increment the inter-consecutive-connect-delay counter - - foreach (IRCConnector connector in m_connectors) - { - if (connector.Enabled) - { - if (!connector.Connected) - { - try - { - // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel); - connector.Connect(); - } - catch (Exception e) - { - m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message); - } - } - else - { - - if (connector.m_pending) - { - if (connector.m_timeout == 0) - { - m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn); - connector.Reconnect(); - } - else - connector.m_timeout--; - } - - if (_pdk_ == 0) - { - try - { - connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server)); - connector.m_writer.Flush(); - } - catch (Exception /*e*/) - { - // m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message); - // m_log.Debug(e); - connector.Reconnect(); - } - } - - } - } - } - - // m_log.InfoFormat("[IRC-Watchdog] Status scan completed"); - - } - - #endregion - - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs deleted file mode 100644 index 78f4265..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - // An instance of this class exists for every active region - - internal class RegionState - { - - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(128, 128, 20); - private const int DEBUG_CHANNEL = 2147483647; - - private static int _idk_ = 0; - - // Runtime variables; these values are assigned when the - // IrcState is created and remain constant thereafter. - - internal string Region = String.Empty; - internal string Host = String.Empty; - internal string LocX = String.Empty; - internal string LocY = String.Empty; - internal string MA1 = String.Empty; - internal string MA2 = String.Empty; - internal string IDK = String.Empty; - - // System values - used only be the IRC classes themselves - - internal ChannelState cs = null; // associated IRC configuration - internal Scene scene = null; // associated scene - internal IConfig config = null; // configuration file reference - internal bool enabled = true; - - // This list is used to keep track of who is here, and by - // implication, who is not. - - internal List clients = new List(); - - // Setup runtime variable values - - public RegionState(Scene p_scene, IConfig p_config) - { - - scene = p_scene; - config = p_config; - - Region = scene.RegionInfo.RegionName; - Host = scene.RegionInfo.ExternalHostName; - LocX = Convert.ToString(scene.RegionInfo.RegionLocX); - LocY = Convert.ToString(scene.RegionInfo.RegionLocY); - MA1 = scene.RegionInfo.MasterAvatarFirstName; - MA2 = scene.RegionInfo.MasterAvatarLastName; - IDK = Convert.ToString(_idk_++); - - // OpenChannel conditionally establishes a connection to the - // IRC server. The request will either succeed, or it will - // throw an exception. - - ChannelState.OpenChannel(this, config); - - // Connect channel to world events - - scene.EventManager.OnChatFromWorld += OnSimChat; - scene.EventManager.OnChatFromClient += OnSimChat; - scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; - scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; - - m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region); - - } - - // Auto cleanup when abandoned - - ~RegionState() - { - if (cs != null) - cs.RemoveRegion(this); - } - - // Called by PostInitialize after all regions have been created - - public void Open() - { - cs.Open(this); - enabled = true; - } - - // Called by IRCBridgeModule.Close immediately prior to unload - // of the module for this region. This happens when the region - // is being removed or the server is terminating. The IRC - // BridgeModule will remove the region from the region list - // when control returns. - - public void Close() - { - enabled = false; - cs.Close(this); - } - - // The agent has disconnected, cleanup associated resources - - private void OnClientLoggedOut(IClientAPI client) - { - try - { - if (clients.Contains(client)) - { - if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) - { - m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name); - cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name)); - } - client.OnLogout -= OnClientLoggedOut; - client.OnConnectionClosed -= OnClientLoggedOut; - clients.Remove(client); - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Region {0}]: ClientLoggedOut exception: {1}", Region, ex.Message); - m_log.Debug(ex); - } - } - - // This event indicates that the agent has left the building. We should treat that the same - // as if the agent has logged out (we don't want cross-region noise - or do we?) - - private void OnMakeChildAgent(ScenePresence presence) - { - - IClientAPI client = presence.ControllingClient; - - try - { - if (clients.Contains(client)) - { - if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) - { - string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); - m_log.DebugFormat("[IRC-Region {0}] {1} has left", Region, clientName); - cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", clientName)); - } - client.OnLogout -= OnClientLoggedOut; - client.OnConnectionClosed -= OnClientLoggedOut; - clients.Remove(client); - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Region {0}]: MakeChildAgent exception: {1}", Region, ex.Message); - m_log.Debug(ex); - } - - } - - // An agent has entered the region (from another region). Add the client to the locally - // known clients list - - private void OnMakeRootAgent(ScenePresence presence) - { - - IClientAPI client = presence.ControllingClient; - - try - { - if (!clients.Contains(client)) - { - client.OnLogout += OnClientLoggedOut; - client.OnConnectionClosed += OnClientLoggedOut; - clients.Add(client); - if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) - { - string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); - m_log.DebugFormat("[IRC-Region {0}] {1} has arrived", Region, clientName); - cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has arrived", clientName)); - } - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message); - m_log.Debug(ex); - } - - } - - // This handler detects chat events int he virtual world. - - public void OnSimChat(Object sender, OSChatMessage msg) - { - - // early return if this comes from the IRC forwarder - - if (cs.irc.Equals(sender)) return; - - // early return if nothing to forward - - if (msg.Message.Length == 0) return; - - // check for commands coming from avatars or in-world - // object (if commands are enabled) - - if (cs.CommandsEnabled && msg.Channel == cs.CommandChannel) - { - - m_log.DebugFormat("[IRC-Region {0}] command on channel {1}: {2}", Region, msg.Channel, msg.Message); - - string[] messages = msg.Message.Split(' '); - string command = messages[0].ToLower(); - - try - { - switch (command) - { - - // These commands potentially require a change in the - // underlying ChannelState. - - case "server": - cs.Close(this); - cs = cs.UpdateServer(this, messages[1]); - cs.Open(this); - break; - case "port": - cs.Close(this); - cs = cs.UpdatePort(this, messages[1]); - cs.Open(this); - break; - case "channel": - cs.Close(this); - cs = cs.UpdateChannel(this, messages[1]); - cs.Open(this); - break; - case "nick": - cs.Close(this); - cs = cs.UpdateNickname(this, messages[1]); - cs.Open(this); - break; - - // These may also (but are less likely) to require a - // change in ChannelState. - - case "client-reporting": - cs = cs.UpdateClientReporting(this, messages[1]); - break; - case "in-channel": - cs = cs.UpdateRelayIn(this, messages[1]); - break; - case "out-channel": - cs = cs.UpdateRelayOut(this, messages[1]); - break; - - // These are all taken to be temporary changes in state - // so the underlying connector remains intact. But note - // that with regions sharing a connector, there could - // be interference. - - case "close": - enabled = false; - cs.Close(this); - break; - - case "connect": - enabled = true; - cs.Open(this); - break; - - case "reconnect": - enabled = true; - cs.Close(this); - cs.Open(this); - break; - - // This one is harmless as far as we can judge from here. - // If it is not, then the complaints will eventually make - // that evident. - - default: - m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}", - Region, msg.Message); - cs.irc.Send(msg.Message); - break; - } - } - catch (Exception ex) - { - m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}", - Region, ex.Message); - m_log.Debug(ex); - } - - return; - - } - - // The command channel remains enabled, even if we have otherwise disabled the IRC - // interface. - - if (!enabled) - return; - - // drop messages unless they are on a valid in-world - // channel as configured in the ChannelState - - if (!cs.ValidInWorldChannels.Contains(msg.Channel)) - { - m_log.DebugFormat("[IRC-Region {0}] dropping message {1} on channel {2}", Region, msg, msg.Channel); - return; - } - - ScenePresence avatar = null; - string fromName = msg.From; - - if (msg.Sender != null) - { - avatar = scene.GetScenePresence(msg.Sender.AgentId); - if (avatar != null) fromName = avatar.Name; - } - - if (!cs.irc.Connected) - { - m_log.WarnFormat("[IRC-Region {0}] IRCConnector not connected: dropping message from {1}", Region, fromName); - return; - } - - m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message); - - if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL)) - { - string txt = msg.Message; - if (txt.StartsWith("/me ")) - txt = String.Format("{0} {1}", fromName, msg.Message.Substring(4)); - - cs.irc.PrivMsg(cs.PrivateMessageFormat, fromName, Region, txt); - return; - } - - if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword && - msg.Channel == cs.RelayChannelOut) - { - Match m = cs.AccessPasswordRegex.Match(msg.Message); - if (null != m) - { - m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(), - m.Groups["message"].ToString()); - cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(), - scene.RegionInfo.RegionName, m.Groups["message"].ToString()); - } - } - } - - // This method gives the region an opportunity to interfere with - // message delivery. For now we just enforce the enable/disable - // flag. - - internal void OSChat(Object irc, OSChatMessage msg) - { - if (enabled) - { - // m_log.DebugFormat("[IRC-OSCHAT] Region {0} being sent message", region.Region); - msg.Scene = scene; - scene.EventManager.TriggerOnChatBroadcast(irc, msg); - } - } - - // This supports any local message traffic that might be needed in - // support of command processing. At present there is none. - - internal void LocalChat(string msg) - { - if (enabled) - { - OSChatMessage osm = new OSChatMessage(); - osm.From = "IRC Agent"; - osm.Message = msg; - osm.Type = ChatTypeEnum.Region; - osm.Position = CenterOfRegion; - osm.Sender = null; - osm.SenderUUID = OpenMetaverse.UUID.Zero; // Hmph! Still? - osm.Channel = 0; - OSChat(this, osm); - } - } - - } - -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs deleted file mode 100644 index f032319..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Combat/CombatModule.cs +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Xml; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework.Communications.Cache; - -namespace OpenSim.Region.Environment.Modules.Avatar.Combat.CombatModule -{ - public class CombatModule : IRegionModule - { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Region UUIDS indexed by AgentID - /// - //private Dictionary m_rootAgents = new Dictionary(); - - /// - /// Scenes by Region Handle - /// - private Dictionary m_scenel = new Dictionary(); - - /// - /// Startup - /// - /// - /// - public void Initialise(Scene scene, IConfigSource config) - { - lock (m_scenel) - { - if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle)) - { - m_scenel[scene.RegionInfo.RegionHandle] = scene; - } - else - { - m_scenel.Add(scene.RegionInfo.RegionHandle, scene); - } - } - - scene.EventManager.OnAvatarKilled += KillAvatar; - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "CombatModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - private void KillAvatar(uint killerObjectLocalID, ScenePresence DeadAvatar) - { - if (killerObjectLocalID == 0) - DeadAvatar.ControllingClient.SendAgentAlertMessage("You committed suicide!", true); - else - { - bool foundResult = false; - string resultstring = ""; - List allav = DeadAvatar.Scene.GetScenePresences(); - try - { - foreach (ScenePresence av in allav) - { - if (av.LocalId == killerObjectLocalID) - { - av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname); - resultstring = av.Firstname + " " + av.Lastname; - foundResult = true; - } - } - } catch (System.InvalidOperationException) - { - - } - - if (!foundResult) - { - SceneObjectPart part = DeadAvatar.Scene.GetSceneObjectPart(killerObjectLocalID); - if (part != null) - { - ScenePresence av = DeadAvatar.Scene.GetScenePresence(part.OwnerID); - if (av != null) - { - av.ControllingClient.SendAlertMessage("You fragged " + DeadAvatar.Firstname + " " + DeadAvatar.Lastname); - resultstring = av.Firstname + " " + av.Lastname; - DeadAvatar.ControllingClient.SendAgentAlertMessage("You got killed by " + resultstring + "!", true); - } - else - { - string killer = DeadAvatar.Scene.CommsManager.UUIDNameRequestString(part.OwnerID); - DeadAvatar.ControllingClient.SendAgentAlertMessage("You impaled yourself on " + part.Name + " owned by " + killer +"!", true); - } - //DeadAvatar.Scene. part.ObjectOwner - } - else - { - DeadAvatar.ControllingClient.SendAgentAlertMessage("You died!", true); - } - } - } - DeadAvatar.Health = 100; - DeadAvatar.Scene.TeleportClientHome(DeadAvatar.UUID, DeadAvatar.ControllingClient); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs deleted file mode 100644 index 5ac5dbe..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeModule.cs +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.Avatar.Chat; - -namespace OpenSim.Region.Environment.Modules.Avatar.Concierge -{ - public class ConciergeModule : ChatModule, IRegionModule - { - private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const int DEBUG_CHANNEL = 2147483647; - - private List _scenes = new List(); - private List _conciergedScenes = new List(); - private Dictionary> _sceneAttendees = - new Dictionary>(); - private Dictionary _attendeeNames = - new Dictionary(); - - private bool _replacingChatModule = false; - - private IConfig _config; - - private string _whoami = "conferencier"; - private Regex _regions = null; - private string _welcomes = null; - private int _conciergeChannel = 42; - private string _announceEntering = "{0} enters {1} (now {2} visitors in this region)"; - private string _announceLeaving = "{0} leaves {1} (back to {2} visitors in this region)"; - private string _xmlRpcPassword = String.Empty; - private string _brokerURI = String.Empty; - - internal object _syncy = new object(); - - #region IRegionModule Members - public override void Initialise(Scene scene, IConfigSource config) - { - try - { - if ((_config = config.Configs["Concierge"]) == null) - { - //_log.InfoFormat("[Concierge]: no configuration section [Concierge] in OpenSim.ini: module not configured"); - return; - } - - if (!_config.GetBoolean("enabled", false)) - { - //_log.InfoFormat("[Concierge]: module disabled by OpenSim.ini configuration"); - return; - } - } - catch (Exception) - { - _log.Info("[Concierge]: module not configured"); - return; - } - - // check whether ChatModule has been disabled: if yes, - // then we'll "stand in" - try - { - if (config.Configs["Chat"] == null) - { - _replacingChatModule = false; - } - else - { - _replacingChatModule = !config.Configs["Chat"].GetBoolean("enabled", true); - } - } - catch (Exception) - { - _replacingChatModule = false; - } - _log.InfoFormat("[Concierge] {0} ChatModule", _replacingChatModule ? "replacing" : "not replacing"); - - - // take note of concierge channel and of identity - _conciergeChannel = config.Configs["Concierge"].GetInt("concierge_channel", _conciergeChannel); - _whoami = _config.GetString("whoami", "conferencier"); - _welcomes = _config.GetString("welcomes", _welcomes); - _announceEntering = _config.GetString("announce_entering", _announceEntering); - _announceLeaving = _config.GetString("announce_leaving", _announceLeaving); - _xmlRpcPassword = _config.GetString("password", _xmlRpcPassword); - _brokerURI = _config.GetString("broker", _brokerURI); - - _log.InfoFormat("[Concierge] reporting as \"{0}\" to our users", _whoami); - - // calculate regions Regex - if (_regions == null) - { - string regions = _config.GetString("regions", String.Empty); - if (!String.IsNullOrEmpty(regions)) - { - _regions = new Regex(@regions, RegexOptions.Compiled | RegexOptions.IgnoreCase); - } - } - - scene.CommsManager.HttpServer.AddXmlRPCHandler("concierge_update_welcome", XmlRpcUpdateWelcomeMethod, false); - - lock (_syncy) - { - if (!_scenes.Contains(scene)) - { - _scenes.Add(scene); - - if (_regions == null || _regions.IsMatch(scene.RegionInfo.RegionName)) - _conciergedScenes.Add(scene); - - // subscribe to NewClient events - scene.EventManager.OnNewClient += OnNewClient; - - // subscribe to *Chat events - scene.EventManager.OnChatFromWorld += OnChatFromWorld; - if (!_replacingChatModule) - scene.EventManager.OnChatFromClient += OnChatFromClient; - scene.EventManager.OnChatBroadcast += OnChatBroadcast; - - // subscribe to agent change events - scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; - scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; - } - } - _log.InfoFormat("[Concierge]: initialized for {0}", scene.RegionInfo.RegionName); - } - - public override void PostInitialise() - { - } - - public override void Close() - { - } - - public override string Name - { - get { return "ConciergeModule"; } - } - - public override bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region ISimChat Members - public override void OnChatBroadcast(Object sender, OSChatMessage c) - { - if (_replacingChatModule) - { - // distribute chat message to each and every avatar in - // the region - base.OnChatBroadcast(sender, c); - } - - // TODO: capture logic - return; - } - - public override void OnChatFromClient(Object sender, OSChatMessage c) - { - if (_replacingChatModule) - { - // replacing ChatModule: need to redistribute - // ChatFromClient to interested subscribers - c = FixPositionOfChatMessage(c); - - Scene scene = (Scene)c.Scene; - scene.EventManager.TriggerOnChatFromClient(sender, c); - - if (_conciergedScenes.Contains(c.Scene)) - { - // when we are replacing ChatModule, we treat - // OnChatFromClient like OnChatBroadcast for - // concierged regions, effectively extending the - // range of chat to cover the whole - // region. however, we don't do this for whisper - // (got to have some privacy) - if (c.Type != ChatTypeEnum.Whisper) - { - base.OnChatBroadcast(sender, c); - return; - } - } - - // redistribution will be done by base class - base.OnChatFromClient(sender, c); - } - - // TODO: capture chat - return; - } - - public override void OnChatFromWorld(Object sender, OSChatMessage c) - { - if (_replacingChatModule) - { - if (_conciergedScenes.Contains(c.Scene)) - { - // when we are replacing ChatModule, we treat - // OnChatFromClient like OnChatBroadcast for - // concierged regions, effectively extending the - // range of chat to cover the whole - // region. however, we don't do this for whisper - // (got to have some privacy) - if (c.Type != ChatTypeEnum.Whisper) - { - base.OnChatBroadcast(sender, c); - return; - } - } - - base.OnChatFromWorld(sender, c); - } - return; - } - #endregion - - - public override void OnNewClient(IClientAPI client) - { - client.OnLogout += OnClientLoggedOut; - - if (_replacingChatModule) - client.OnChatFromClient += OnChatFromClient; - } - - - - public void OnClientLoggedOut(IClientAPI client) - { - client.OnLogout -= OnClientLoggedOut; - client.OnConnectionClosed -= OnClientLoggedOut; - - if (_conciergedScenes.Contains(client.Scene)) - { - _log.DebugFormat("[Concierge]: {0} logs off from {1}", client.Name, client.Scene.RegionInfo.RegionName); - RemoveFromAttendeeList(client.AgentId, client.Name, client.Scene); - AnnounceToAgentsRegion(client.Scene, String.Format(_announceLeaving, client.Name, client.Scene.RegionInfo.RegionName, - _sceneAttendees[client.Scene].Count)); - UpdateBroker(client.Scene); - } - } - - - public void OnMakeRootAgent(ScenePresence agent) - { - if (_conciergedScenes.Contains(agent.Scene)) - { - _log.DebugFormat("[Concierge]: {0} enters {1}", agent.Name, agent.Scene.RegionInfo.RegionName); - AddToAttendeeList(agent.UUID, agent.Name, agent.Scene); - WelcomeAvatar(agent, agent.Scene); - AnnounceToAgentsRegion(agent.Scene, String.Format(_announceEntering, agent.Name, agent.Scene.RegionInfo.RegionName, - _sceneAttendees[agent.Scene].Count)); - UpdateBroker(agent.Scene); - } - } - - - public void OnMakeChildAgent(ScenePresence agent) - { - if (_conciergedScenes.Contains(agent.Scene)) - { - _log.DebugFormat("[Concierge]: {0} leaves {1}", agent.Name, agent.Scene.RegionInfo.RegionName); - RemoveFromAttendeeList(agent.UUID, agent.Name, agent.Scene); - AnnounceToAgentsRegion(agent.Scene, String.Format(_announceLeaving, agent.Name, agent.Scene.RegionInfo.RegionName, - _sceneAttendees[agent.Scene].Count)); - UpdateBroker(agent.Scene); - } - } - - protected void AddToAttendeeList(UUID agentID, string name, Scene scene) - { - lock (_sceneAttendees) - { - if (!_sceneAttendees.ContainsKey(scene)) - _sceneAttendees[scene] = new List(); - - List attendees = _sceneAttendees[scene]; - if (!attendees.Contains(agentID)) - { - attendees.Add(agentID); - _attendeeNames[agentID] = name; - } - } - } - - protected void RemoveFromAttendeeList(UUID agentID, String name, IScene scene) - { - lock (_sceneAttendees) - { - if (!_sceneAttendees.ContainsKey(scene)) - { - _log.WarnFormat("[Concierge]: attendee list missing for region {0}", scene.RegionInfo.RegionName); - return; - } - - List attendees = _sceneAttendees[scene]; - if (!attendees.Contains(agentID)) - { - _log.WarnFormat("[Concierge]: avatar {0} must have sneaked in to region {1} earlier", - name, scene.RegionInfo.RegionName); - return; - } - - attendees.Remove(agentID); - _attendeeNames.Remove(agentID); - } - } - - protected void UpdateBroker(IScene scene) - { - if (String.IsNullOrEmpty(_brokerURI)) - return; - - string uri = String.Format(_brokerURI, scene.RegionInfo.RegionName, scene.RegionInfo.RegionID); - - // get attendee list for the scene - List attendees; - lock (_sceneAttendees) - { - if (!_sceneAttendees.ContainsKey(scene)) - { - _log.DebugFormat("[Concierge]: attendee list missing for region {0}", scene.RegionInfo.RegionName); - return; - } - - attendees = _sceneAttendees[scene]; - } - - // create XML sniplet - StringBuilder list = new StringBuilder(); - if (0 == attendees.Count) - { - list.Append(String.Format("", - scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, - DateTime.UtcNow.ToString("s"))); - } - else - { - list.Append(String.Format("\n", - attendees.Count, scene.RegionInfo.RegionName, - scene.RegionInfo.RegionID, - DateTime.UtcNow.ToString("s"))); - foreach (UUID uuid in attendees) - { - string name = _attendeeNames[uuid]; - list.Append(String.Format(" \n", name, uuid)); - } - list.Append(""); - } - string payload = list.ToString(); - - // post via REST to broker - HttpWebRequest updatePost = WebRequest.Create(uri) as HttpWebRequest; - updatePost.Method = "POST"; - updatePost.ContentType = "text/xml"; - updatePost.ContentLength = payload.Length; - updatePost.UserAgent = "OpenSim.Concierge"; - - try - { - StreamWriter payloadStream = new StreamWriter(updatePost.GetRequestStream()); - payloadStream.Write(payload); - payloadStream.Close(); - - updatePost.BeginGetResponse(UpdateBrokerDone, updatePost); - _log.DebugFormat("[Concierge] async broker POST to {0} started", uri); - } - catch (WebException we) - { - _log.ErrorFormat("[Concierge] async broker POST to {0} failed: {1}", uri, we.Status); - } - } - - private void UpdateBrokerDone(IAsyncResult result) - { - HttpWebRequest updatePost = null; - try - { - updatePost = result.AsyncState as HttpWebRequest; - using (HttpWebResponse response = updatePost.EndGetResponse(result) as HttpWebResponse) - { - _log.DebugFormat("[Concierge] broker update: status {0}", response.StatusCode); - } - } - catch (WebException we) - { - string uri = updatePost.RequestUri.OriginalString; - _log.ErrorFormat("[Concierge] broker update to {0} failed with status {1}", uri, we.Status); - if (null != we.Response) - { - using (HttpWebResponse resp = we.Response as HttpWebResponse) - { - _log.ErrorFormat("[Concierge] response from {0} status code: {1}", uri, resp.StatusCode); - _log.ErrorFormat("[Concierge] response from {0} status desc: {1}", uri, resp.StatusDescription); - _log.ErrorFormat("[Concierge] response from {0} server: {1}", uri, resp.Server); - - if (resp.ContentLength > 0) - { - StreamReader content = new StreamReader(resp.GetResponseStream()); - _log.ErrorFormat("[Concierge] response from {0} content: {1}", uri, content.ReadToEnd()); - content.Close(); - } - } - } - } - } - - protected void WelcomeAvatar(ScenePresence agent, Scene scene) - { - // welcome mechanics: check whether we have a welcomes - // directory set and wether there is a region specific - // welcome file there: if yes, send it to the agent - if (!String.IsNullOrEmpty(_welcomes)) - { - string[] welcomes = new string[] { - Path.Combine(_welcomes, agent.Scene.RegionInfo.RegionName), - Path.Combine(_welcomes, "DEFAULT")}; - foreach (string welcome in welcomes) - { - if (File.Exists(welcome)) - { - try - { - string[] welcomeLines = File.ReadAllLines(welcome); - foreach (string l in welcomeLines) - { - AnnounceToAgent(agent, String.Format(l, agent.Name, scene.RegionInfo.RegionName, _whoami)); - } - } - catch (IOException ioe) - { - _log.ErrorFormat("[Concierge]: run into trouble reading welcome file {0} for region {1} for avatar {2}: {3}", - welcome, scene.RegionInfo.RegionName, agent.Name, ioe); - } - catch (FormatException fe) - { - _log.ErrorFormat("[Concierge]: welcome file {0} is malformed: {1}", welcome, fe); - } - } - return; - } - _log.DebugFormat("[Concierge]: no welcome message for region {0}", scene.RegionInfo.RegionName); - } - } - - static private Vector3 PosOfGod = new Vector3(128, 128, 9999); - - // protected void AnnounceToAgentsRegion(Scene scene, string msg) - // { - // ScenePresence agent = null; - // if ((client.Scene is Scene) && (client.Scene as Scene).TryGetAvatar(client.AgentId, out agent)) - // AnnounceToAgentsRegion(agent, msg); - // else - // _log.DebugFormat("[Concierge]: could not find an agent for client {0}", client.Name); - // } - - protected void AnnounceToAgentsRegion(IScene scene, string msg) - { - OSChatMessage c = new OSChatMessage(); - c.Message = msg; - c.Type = ChatTypeEnum.Say; - c.Channel = 0; - c.Position = PosOfGod; - c.From = _whoami; - c.Sender = null; - c.SenderUUID = UUID.Zero; - c.Scene = scene; - - if (scene is Scene) - (scene as Scene).EventManager.TriggerOnChatBroadcast(this, c); - } - - protected void AnnounceToAgent(ScenePresence agent, string msg) - { - OSChatMessage c = new OSChatMessage(); - c.Message = msg; - c.Type = ChatTypeEnum.Say; - c.Channel = 0; - c.Position = PosOfGod; - c.From = _whoami; - c.Sender = null; - c.SenderUUID = UUID.Zero; - c.Scene = agent.Scene; - - agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, _whoami, UUID.Zero, - (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); - } - - private static void checkStringParameters(XmlRpcRequest request, string[] param) - { - Hashtable requestData = (Hashtable) request.Params[0]; - foreach (string p in param) - { - if (!requestData.Contains(p)) - throw new Exception(String.Format("missing string parameter {0}", p)); - if (String.IsNullOrEmpty((string)requestData[p])) - throw new Exception(String.Format("parameter {0} is empty", p)); - } - } - - public XmlRpcResponse XmlRpcUpdateWelcomeMethod(XmlRpcRequest request) - { - _log.Info("[Concierge]: processing UpdateWelcome request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - Hashtable requestData = (Hashtable)request.Params[0]; - checkStringParameters(request, new string[] { "password", "region", "welcome" }); - - // check password - if (!String.IsNullOrEmpty(_xmlRpcPassword) && - (string)requestData["password"] != _xmlRpcPassword) throw new Exception("wrong password"); - - if (String.IsNullOrEmpty(_welcomes)) - throw new Exception("welcome templates are not enabled, ask your OpenSim operator to set the \"welcomes\" option in the [Concierge] section of OpenSim.ini"); - - string msg = (string)requestData["welcome"]; - if (String.IsNullOrEmpty(msg)) - throw new Exception("empty parameter \"welcome\""); - - string regionName = (string)requestData["region"]; - IScene scene = _scenes.Find(delegate(IScene s) { return s.RegionInfo.RegionName == regionName; }); - if (scene == null) - throw new Exception(String.Format("unknown region \"{0}\"", regionName)); - - if (!_conciergedScenes.Contains(scene)) - throw new Exception(String.Format("region \"{0}\" is not a concierged region.", regionName)); - - string welcome = Path.Combine(_welcomes, regionName); - if (File.Exists(welcome)) - { - _log.InfoFormat("[Concierge]: UpdateWelcome: updating existing template \"{0}\"", welcome); - string welcomeBackup = String.Format("{0}~", welcome); - if (File.Exists(welcomeBackup)) - File.Delete(welcomeBackup); - File.Move(welcome, welcomeBackup); - } - File.WriteAllText(welcome, msg); - - responseData["success"] = "true"; - response.Value = responseData; - } - catch (Exception e) - { - _log.InfoFormat("[Concierge]: UpdateWelcome failed: {0}", e.Message); - - responseData["success"] = "false"; - responseData["error"] = e.Message; - - response.Value = responseData; - } - _log.Debug("[Concierge]: done processing UpdateWelcome request"); - return response; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py b/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py deleted file mode 100755 index 1c088fb..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Concierge/ConciergeServer.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- -# -# Copyright (c) Contributors, http://opensimulator.org/ -# See CONTRIBUTORS.TXT for a full list of copyright holders. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of the OpenSim Project nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -import logging -import BaseHTTPServer -import optparse -import xml.etree.ElementTree as ET -import xml.parsers.expat - - -# enable debug level logging -logging.basicConfig(level = logging.DEBUG, - format='%(asctime)s %(levelname)s %(message)s') - -options = None - -# subclassed HTTPRequestHandler -class ConciergeHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def logRequest(self): - logging.info('[ConciergeHandler] %(command)s request: %(host)s:%(port)d --- %(path)s', - dict(command = self.command, - host = self.client_address[0], - port = self.client_address[1], - path = self.path)) - - def logResponse(self, status): - logging.info('[ConciergeHandler] %(command)s returned %(status)d', - dict(command = self.command, - status = status)) - - - def do_HEAD(self): - self.logRequest() - - self.send_response(200) - self.send_header('Content-type', 'text/html') - self.end_headers() - - self.logResponse(200) - - def dumpXml(self, xml): - logging.debug('[ConciergeHandler] %s', xml.tag) - for attr in xml.attrib: - logging.debug('[ConciergeHandler] %s [%s] %s', xml.tag, attr, xml.attrib[attr]) - for kid in xml.getchildren(): - self.dumpXml(kid) - - def do_POST(self): - self.logRequest() - hdrs = {} - for hdr in self.headers.headers: - logging.debug('[ConciergeHandler] POST: header: %s', hdr.rstrip()) - - length = int(self.headers.getheader('Content-Length')) - content = self.rfile.read(length) - self.rfile.close() - - logging.debug('[ConciergeHandler] POST: content: %s', content) - try: - postXml = ET.fromstring(content) - self.dumpXml(postXml) - except xml.parsers.expat.ExpatError, xmlError: - logging.error('[ConciergeHandler] POST illformed:%s', xmlError) - self.send_response(500) - return - - if not options.fail: - self.send_response(200) - self.send_header('Content-Type', 'text/html') - self.send_header('Content-Length', len('')) - self.end_headers() - self.logResponse(200) - self.wfile.write('') - self.wfile.close() - else: - self.send_response(500) - self.send_header('Content-Type', 'text/html') - self.send_header('Content-Length', len('gotcha!')) - self.end_headers() - self.wfile.write('gotcha!') - self.wfile.close() - - self.logResponse(500) - - def log_request(code, size): - pass - -if __name__ == '__main__': - - logging.info('[ConciergeServer] Concierge Broker Test Server starting') - - parser = optparse.OptionParser() - parser.add_option('-p', '--port', dest = 'port', help = 'port to listen on', metavar = 'PORT') - parser.add_option('-f', '--fail', dest = 'fail', action = 'store_true', help = 'always fail POST requests') - - (options, args) = parser.parse_args() - - httpServer = BaseHTTPServer.HTTPServer(('', 8080), ConciergeHandler) - try: - httpServer.serve_forever() - except KeyboardInterrupt: - logging.info('[ConciergeServer] terminating') - - httpServer.server_close() diff --git a/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs deleted file mode 100644 index 1ec5e9b..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs +++ /dev/null @@ -1,1605 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Xml; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney -{ - /// - /// Demo Economy/Money Module. This is not a production quality money/economy module! - /// This is a demo for you to use when making one that works for you. - /// // To use the following you need to add: - /// -helperuri
- /// to the command line parameters you use to start up your client - /// This commonly looks like -helperuri http://127.0.0.1:9000/ - /// - /// Centralized grid structure example using OpenSimWi Redux revision 9+ - /// svn co https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux - ///
- public class SampleMoneyModule : IMoneyModule, IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Where Stipends come from and Fees go to. - /// - // private UUID EconomyBaseAccount = UUID.Zero; - - private float EnergyEfficiency = 0f; - private bool gridmode = false; - // private ObjectPaid handerOnObjectPaid; - private bool m_enabled = true; - - private IConfigSource m_gConfig; - - private bool m_keepMoneyAcrossLogins = true; - private Dictionary m_KnownClientFunds = new Dictionary(); - // private string m_LandAddress = String.Empty; - - private int m_minFundsBeforeRefresh = 100; - private string m_MoneyAddress = String.Empty; - - /// - /// Region UUIDS indexed by AgentID - /// - private Dictionary m_rootAgents = new Dictionary(); - - /// - /// Scenes by Region Handle - /// - private Dictionary m_scenel = new Dictionary(); - - private int m_stipend = 1000; - - private int ObjectCapacity = 45000; - private int ObjectCount = 0; - private int PriceEnergyUnit = 0; - private int PriceGroupCreate = 0; - private int PriceObjectClaim = 0; - private float PriceObjectRent = 0f; - private float PriceObjectScaleFactor = 0f; - private int PriceParcelClaim = 0; - private float PriceParcelClaimFactor = 0f; - private int PriceParcelRent = 0; - private int PricePublicObjectDecay = 0; - private int PricePublicObjectDelete = 0; - private int PriceRentLight = 0; - private int PriceUpload = 0; - private int TeleportMinPrice = 0; - - private float TeleportPriceExponent = 0f; - // private int UserLevelPaysFees = 2; - // private Scene XMLRPCHandler; - - #region IMoneyModule Members - - public event ObjectPaid OnObjectPaid; - - /// - /// Startup - /// - /// - /// - public void Initialise(Scene scene, IConfigSource config) - { - m_gConfig = config; - - IConfig startupConfig = m_gConfig.Configs["Startup"]; - IConfig economyConfig = m_gConfig.Configs["Economy"]; - - - ReadConfigAndPopulate(scene, startupConfig, "Startup"); - ReadConfigAndPopulate(scene, economyConfig, "Economy"); - - if (m_enabled) - { - scene.RegisterModuleInterface(this); - BaseHttpServer httpServer = scene.CommsManager.HttpServer; - - lock (m_scenel) - { - if (m_scenel.Count == 0) - { - // XMLRPCHandler = scene; - - // To use the following you need to add: - // -helperuri
- // to the command line parameters you use to start up your client - // This commonly looks like -helperuri http://127.0.0.1:9000/ - - if (m_MoneyAddress.Length > 0) - { - // Centralized grid structure using OpenSimWi Redux revision 9+ - // https://opensimwiredux.svn.sourceforge.net/svnroot/opensimwiredux - httpServer.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate); - httpServer.AddXmlRPCHandler("userAlert", UserAlert); - } - else - { - // Local Server.. enables functionality only. - httpServer.AddXmlRPCHandler("getCurrencyQuote", quote_func); - httpServer.AddXmlRPCHandler("buyCurrency", buy_func); - httpServer.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func); - httpServer.AddXmlRPCHandler("buyLandPrep", landBuy_func); - } - } - - if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle)) - { - m_scenel[scene.RegionInfo.RegionHandle] = scene; - } - else - { - m_scenel.Add(scene.RegionInfo.RegionHandle, scene); - } - } - - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnMoneyTransfer += MoneyTransferAction; - scene.EventManager.OnClientClosed += ClientClosed; - scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; - scene.EventManager.OnClientClosed += ClientLoggedOut; - scene.EventManager.OnValidateLandBuy += ValidateLandBuy; - scene.EventManager.OnLandBuy += processLandBuy; - } - } - - // Please do not refactor these to be just one method - // Existing implementations need the distinction - // - public void ApplyUploadCharge(UUID agentID) - { - } - - public void ApplyGroupCreationCharge(UUID agentID) - { - } - - public void ApplyCharge(UUID agentID, int amount, string text) - { - } - - public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount) - { - string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID)); - - bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description); - - if (m_MoneyAddress.Length == 0) - BalanceUpdate(fromID, toID, give_result, description); - - return give_result; - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "BetaGridLikeMoneyModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - /// - /// Parse Configuration - /// - /// - /// - /// - private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string config) - { - if (config == "Startup" && startupConfig != null) - { - gridmode = startupConfig.GetBoolean("gridmode", false); - m_enabled = (startupConfig.GetString("economymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule"); - } - - if (config == "Economy" && startupConfig != null) - { - ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000); - PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100); - PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10); - PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4); - PricePublicObjectDelete = startupConfig.GetInt("PricePublicObjectDelete", 4); - PriceParcelClaim = startupConfig.GetInt("PriceParcelClaim", 1); - PriceParcelClaimFactor = startupConfig.GetFloat("PriceParcelClaimFactor", 1f); - PriceUpload = startupConfig.GetInt("PriceUpload", 0); - PriceRentLight = startupConfig.GetInt("PriceRentLight", 5); - TeleportMinPrice = startupConfig.GetInt("TeleportMinPrice", 2); - TeleportPriceExponent = startupConfig.GetFloat("TeleportPriceExponent", 2f); - EnergyEfficiency = startupConfig.GetFloat("EnergyEfficiency", 1); - PriceObjectRent = startupConfig.GetFloat("PriceObjectRent", 1); - PriceObjectScaleFactor = startupConfig.GetFloat("PriceObjectScaleFactor", 10); - PriceParcelRent = startupConfig.GetInt("PriceParcelRent", 1); - PriceGroupCreate = startupConfig.GetInt("PriceGroupCreate", -1); - // string EBA = startupConfig.GetString("EconomyBaseAccount", UUID.Zero.ToString()); - // Helpers.TryParse(EBA, out EconomyBaseAccount); - - // UserLevelPaysFees = startupConfig.GetInt("UserLevelPaysFees", -1); - m_stipend = startupConfig.GetInt("UserStipend", 500); - m_minFundsBeforeRefresh = startupConfig.GetInt("IssueStipendWhenClientIsBelowAmount", 10); - m_keepMoneyAcrossLogins = startupConfig.GetBoolean("KeepMoneyAcrossLogins", true); - m_MoneyAddress = startupConfig.GetString("CurrencyServer", String.Empty); - // m_LandAddress = startupConfig.GetString("LandServer", String.Empty); - } - - // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. - scene.SetObjectCapacity(ObjectCapacity); - } - - public EconomyData GetEconomyData() - { - EconomyData edata = new EconomyData(); - edata.ObjectCapacity = ObjectCapacity; - edata.ObjectCount = ObjectCount; - edata.PriceEnergyUnit = PriceEnergyUnit; - edata.PriceGroupCreate = PriceGroupCreate; - edata.PriceObjectClaim = PriceObjectClaim; - edata.PriceObjectRent = PriceObjectRent; - edata.PriceObjectScaleFactor = PriceObjectScaleFactor; - edata.PriceParcelClaim = PriceParcelClaim; - edata.PriceParcelClaimFactor = PriceParcelClaimFactor; - edata.PriceParcelRent = PriceParcelRent; - edata.PricePublicObjectDecay = PricePublicObjectDecay; - edata.PricePublicObjectDelete = PricePublicObjectDelete; - edata.PriceRentLight = PriceRentLight; - edata.PriceUpload = PriceUpload; - edata.TeleportMinPrice = TeleportMinPrice; - return edata; - } - - private void GetClientFunds(IClientAPI client) - { - // Here we check if we're in grid mode - // I imagine that the 'check balance' - // function for the client should be here or shortly after - - if (gridmode) - { - if (m_MoneyAddress.Length == 0) - { - CheckExistAndRefreshFunds(client.AgentId); - } - else - { - bool childYN = true; - ScenePresence agent = null; - //client.SecureSessionId; - Scene s = LocateSceneClientIn(client.AgentId); - if (s != null) - { - agent = s.GetScenePresence(client.AgentId); - if (agent != null) - childYN = agent.IsChildAgent; - } - if (s != null && agent != null && childYN == false) - { - //s.RegionInfo.RegionHandle; - UUID agentID = UUID.Zero; - int funds = 0; - - Hashtable hbinfo = - GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID, - s.RegionInfo.regionSecret); - if ((bool) hbinfo["success"] == true) - { - UUID.TryParse((string)hbinfo["agentId"], out agentID); - try - { - funds = (Int32) hbinfo["funds"]; - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentID); - client.SendAlertMessage("Unable to get your money balance, money operations will be unavailable"); - } - catch (InvalidCastException) - { - funds = 0; - } - - m_KnownClientFunds[agentID] = funds; - } - else - { - m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentID, - (string) hbinfo["errorMessage"]); - client.SendAlertMessage((string) hbinfo["errorMessage"]); - } - SendMoneyBalance(client, agentID, client.SessionId, UUID.Zero); - } - } - } - else - { - CheckExistAndRefreshFunds(client.AgentId); - } - - } - - /// - /// New Client Event Handler - /// - /// - private void OnNewClient(IClientAPI client) - { - GetClientFunds(client); - - // Subscribe to Money messages - client.OnEconomyDataRequest += EconomyDataRequestHandler; - client.OnMoneyBalanceRequest += SendMoneyBalance; - client.OnRequestPayPrice += requestPayPrice; - client.OnObjectBuy += ObjectBuy; - client.OnLogout += ClientClosed; - } - - /// - /// Transfer money - /// - /// - /// - /// - /// - private bool doMoneyTransfer(UUID Sender, UUID Receiver, int amount, int transactiontype, string description) - { - bool result = false; - if (amount >= 0) - { - lock (m_KnownClientFunds) - { - // If we don't know about the sender, then the sender can't - // actually be here and therefore this is likely fraud or outdated. - if (m_MoneyAddress.Length == 0) - { - if (m_KnownClientFunds.ContainsKey(Sender)) - { - // Does the sender have enough funds to give? - if (m_KnownClientFunds[Sender] >= amount) - { - // Subtract the funds from the senders account - m_KnownClientFunds[Sender] -= amount; - - // do we know about the receiver? - if (!m_KnownClientFunds.ContainsKey(Receiver)) - { - // Make a record for them so they get the updated balance when they login - CheckExistAndRefreshFunds(Receiver); - } - if (m_enabled) - { - //Add the amount to the Receiver's funds - m_KnownClientFunds[Receiver] += amount; - result = true; - } - } - else - { - // These below are redundant to make this clearer to read - result = false; - } - } - else - { - result = false; - } - } - else - { - result = TransferMoneyonMoneyServer(Sender, Receiver, amount, transactiontype, description); - } - } - } - return result; - } - - - /// - /// Sends the the stored money balance to the client - /// - /// - /// - /// - /// - public void SendMoneyBalance(IClientAPI client, UUID agentID, UUID SessionID, UUID TransactionID) - { - if (client.AgentId == agentID && client.SessionId == SessionID) - { - int returnfunds = 0; - - try - { - returnfunds = GetFundsForAgentID(agentID); - } - catch (Exception e) - { - client.SendAlertMessage(e.Message + " "); - } - - client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); - } - else - { - client.SendAlertMessage("Unable to send your money balance to you!"); - } - } - - /// - /// Gets the current balance for the user from the Grid Money Server - /// - /// - /// - /// - /// - /// - public Hashtable GetBalanceForUserFromMoneyServer(UUID agentId, UUID secureSessionID, UUID regionId, string regionSecret) - { - Hashtable MoneyBalanceRequestParams = new Hashtable(); - MoneyBalanceRequestParams["agentId"] = agentId.ToString(); - MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString(); - MoneyBalanceRequestParams["regionId"] = regionId.ToString(); - MoneyBalanceRequestParams["secret"] = regionSecret; - MoneyBalanceRequestParams["currencySecret"] = ""; // per - region/user currency secret gotten from the money system - - Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorUserBalanceRequest"); - - return MoneyRespData; - } - - - /// - /// Generic XMLRPC client abstraction - /// - /// Hashtable containing parameters to the method - /// Method to invoke - /// Hashtable with success=>bool and other values - public Hashtable genericCurrencyXMLRPCRequest(Hashtable ReqParams, string method) - { - ArrayList SendParams = new ArrayList(); - SendParams.Add(ReqParams); - // Send Request - XmlRpcResponse MoneyResp; - try - { - XmlRpcRequest BalanceRequestReq = new XmlRpcRequest(method, SendParams); - MoneyResp = BalanceRequestReq.Send(m_MoneyAddress, 30000); - } - catch (WebException ex) - { - m_log.ErrorFormat( - "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", - m_MoneyAddress, ex); - - Hashtable ErrorHash = new Hashtable(); - ErrorHash["success"] = false; - ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; - ErrorHash["errorURI"] = ""; - - return ErrorHash; - //throw (ex); - } - catch (SocketException ex) - { - m_log.ErrorFormat( - "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", - m_MoneyAddress, ex); - - Hashtable ErrorHash = new Hashtable(); - ErrorHash["success"] = false; - ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; - ErrorHash["errorURI"] = ""; - - return ErrorHash; - //throw (ex); - } - catch (XmlException ex) - { - m_log.ErrorFormat( - "[MONEY]: Unable to connect to Money Server {0}. Exception {1}", - m_MoneyAddress, ex); - - Hashtable ErrorHash = new Hashtable(); - ErrorHash["success"] = false; - ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; - ErrorHash["errorURI"] = ""; - - return ErrorHash; - } - if (MoneyResp.IsFault) - { - Hashtable ErrorHash = new Hashtable(); - ErrorHash["success"] = false; - ErrorHash["errorMessage"] = "Unable to manage your money at this time. Purchases may be unavailable"; - ErrorHash["errorURI"] = ""; - - return ErrorHash; - } - Hashtable MoneyRespData = (Hashtable) MoneyResp.Value; - - return MoneyRespData; - } - - /// - /// This informs the Money Grid Server that the avatar is in this simulator - /// - /// - /// - /// - /// - /// - public Hashtable claim_user(UUID agentId, UUID secureSessionID, UUID regionId, string regionSecret) - { - Hashtable MoneyBalanceRequestParams = new Hashtable(); - MoneyBalanceRequestParams["agentId"] = agentId.ToString(); - MoneyBalanceRequestParams["secureSessionId"] = secureSessionID.ToString(); - MoneyBalanceRequestParams["regionId"] = regionId.ToString(); - MoneyBalanceRequestParams["secret"] = regionSecret; - - Hashtable MoneyRespData = genericCurrencyXMLRPCRequest(MoneyBalanceRequestParams, "simulatorClaimUserRequest"); - IClientAPI sendMoneyBal = LocateClientObject(agentId); - if (sendMoneyBal != null) - { - SendMoneyBalance(sendMoneyBal, agentId, sendMoneyBal.SessionId, UUID.Zero); - } - return MoneyRespData; - } - - private SceneObjectPart findPrim(UUID objectID) - { - lock (m_scenel) - { - foreach (Scene s in m_scenel.Values) - { - SceneObjectPart part = s.GetSceneObjectPart(objectID); - if (part != null) - { - return part; - } - } - } - return null; - } - - private string resolveObjectName(UUID objectID) - { - SceneObjectPart part = findPrim(objectID); - if (part != null) - { - return part.Name; - } - return String.Empty; - } - - private string resolveAgentName(UUID agentID) - { - // try avatar username surname - Scene scene = GetRandomScene(); - CachedUserInfo profile = scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); - if (profile != null && profile.UserProfile != null) - { - string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName; - return avatarname; - } - else - { - m_log.ErrorFormat( - "[MONEY]: Could not resolve user {0}", - agentID); - } - - return String.Empty; - } - - private void BalanceUpdate(UUID senderID, UUID receiverID, bool transactionresult, string description) - { - IClientAPI sender = LocateClientObject(senderID); - IClientAPI receiver = LocateClientObject(receiverID); - - if (senderID != receiverID) - { - if (sender != null) - { - sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(senderID)); - } - - if (receiver != null) - { - receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(description), GetFundsForAgentID(receiverID)); - } - } - } - - /// - /// Informs the Money Grid Server of a transfer. - /// - /// - /// - /// - /// - public bool TransferMoneyonMoneyServer(UUID sourceId, UUID destId, int amount, int transactiontype, string description) - { - int aggregatePermInventory = 0; - int aggregatePermNextOwner = 0; - int flags = 0; - bool rvalue = false; - - IClientAPI cli = LocateClientObject(sourceId); - if (cli != null) - { - Scene userScene = null; - lock (m_rootAgents) - { - userScene = GetSceneByUUID(m_rootAgents[sourceId]); - } - if (userScene != null) - { - Hashtable ht = new Hashtable(); - ht["agentId"] = sourceId.ToString(); - ht["secureSessionId"] = cli.SecureSessionId.ToString(); - ht["regionId"] = userScene.RegionInfo.originRegionID.ToString(); - ht["secret"] = userScene.RegionInfo.regionSecret; - ht["currencySecret"] = " "; - ht["destId"] = destId.ToString(); - ht["cash"] = amount; - ht["aggregatePermInventory"] = aggregatePermInventory; - ht["aggregatePermNextOwner"] = aggregatePermNextOwner; - ht["flags"] = flags; - ht["transactionType"] = transactiontype; - ht["description"] = description; - - Hashtable hresult = genericCurrencyXMLRPCRequest(ht, "regionMoveMoney"); - - if ((bool) hresult["success"] == true) - { - int funds1 = 0; - int funds2 = 0; - try - { - funds1 = (Int32) hresult["funds"]; - } - catch (InvalidCastException) - { - funds1 = 0; - } - SetLocalFundsForAgentID(sourceId, funds1); - if (m_KnownClientFunds.ContainsKey(destId)) - { - try - { - funds2 = (Int32) hresult["funds2"]; - } - catch (InvalidCastException) - { - funds2 = 0; - } - SetLocalFundsForAgentID(destId, funds2); - } - - - rvalue = true; - } - else - { - cli.SendAgentAlertMessage((string) hresult["errorMessage"], true); - } - } - } - else - { - m_log.ErrorFormat("[MONEY]: Client {0} not found", sourceId.ToString()); - } - - return rvalue; - } - - public int GetRemoteBalance(UUID agentId) - { - int funds = 0; - - IClientAPI aClient = LocateClientObject(agentId); - if (aClient != null) - { - Scene s = LocateSceneClientIn(agentId); - if (s != null) - { - if (m_MoneyAddress.Length > 0) - { - Hashtable hbinfo = - GetBalanceForUserFromMoneyServer(aClient.AgentId, aClient.SecureSessionId, s.RegionInfo.originRegionID, - s.RegionInfo.regionSecret); - if ((bool) hbinfo["success"] == true) - { - try - { - funds = (Int32) hbinfo["funds"]; - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - m_log.ErrorFormat("[MONEY]: While getting the Currency for user {0}, the return funds overflowed.", agentId); - aClient.SendAlertMessage("Unable to get your money balance, money operations will be unavailable"); - } - catch (InvalidCastException) - { - funds = 0; - } - } - else - { - m_log.WarnFormat("[MONEY]: Getting Money for user {0} failed with the following message:{1}", agentId, - (string) hbinfo["errorMessage"]); - aClient.SendAlertMessage((string) hbinfo["errorMessage"]); - } - } - - SetLocalFundsForAgentID(agentId, funds); - SendMoneyBalance(aClient, agentId, aClient.SessionId, UUID.Zero); - } - else - { - m_log.Debug("[MONEY]: Got balance request update for agent that is here, but couldn't find which scene."); - } - } - else - { - m_log.Debug("[MONEY]: Got balance request update for agent that isn't here."); - } - return funds; - } - - public XmlRpcResponse GridMoneyUpdate(XmlRpcRequest request) - { - m_log.Debug("[MONEY]: Dynamic balance update called."); - Hashtable requestData = (Hashtable) request.Params[0]; - - if (requestData.ContainsKey("agentId")) - { - UUID agentId = UUID.Zero; - - UUID.TryParse((string) requestData["agentId"], out agentId); - if (agentId != UUID.Zero) - { - GetRemoteBalance(agentId); - } - else - { - m_log.Debug("[MONEY]: invalid agentId specified, dropping."); - } - } - else - { - m_log.Debug("[MONEY]: no agentId specified, dropping."); - } - XmlRpcResponse r = new XmlRpcResponse(); - Hashtable rparms = new Hashtable(); - rparms["success"] = true; - - r.Value = rparms; - return r; - } - - /// - /// XMLRPC handler to send alert message and sound to client - /// - public XmlRpcResponse UserAlert(XmlRpcRequest request) - { - XmlRpcResponse ret = new XmlRpcResponse(); - Hashtable retparam = new Hashtable(); - Hashtable requestData = (Hashtable) request.Params[0]; - - UUID agentId; - UUID soundId; - UUID regionId; - - UUID.TryParse((string) requestData["agentId"], out agentId); - UUID.TryParse((string) requestData["soundId"], out soundId); - UUID.TryParse((string) requestData["regionId"], out regionId); - string text = (string) requestData["text"]; - string secret = (string) requestData["secret"]; - - Scene userScene = GetSceneByUUID(regionId); - if (userScene != null) - { - if (userScene.RegionInfo.regionSecret == secret) - { - - IClientAPI client = LocateClientObject(agentId); - if (client != null) - { - - if (soundId != UUID.Zero) - client.SendPlayAttachedSound(soundId, UUID.Zero, UUID.Zero, 1.0f, 0); - - client.SendBlueBoxMessage(UUID.Zero, "", text); - - retparam.Add("success", true); - } - else - { - retparam.Add("success", false); - } - } - else - { - retparam.Add("success", false); - } - } - - ret.Value = retparam; - return ret; - } - - # region Standalone box enablers only - - public XmlRpcResponse quote_func(XmlRpcRequest request) - { - Hashtable requestData = (Hashtable) request.Params[0]; - UUID agentId = UUID.Zero; - int amount = 0; - Hashtable quoteResponse = new Hashtable(); - XmlRpcResponse returnval = new XmlRpcResponse(); - - if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) - { - UUID.TryParse((string) requestData["agentId"], out agentId); - try - { - amount = (Int32) requestData["currencyBuy"]; - } - catch (InvalidCastException) - { - } - Hashtable currencyResponse = new Hashtable(); - currencyResponse.Add("estimatedCost", 0); - currencyResponse.Add("currencyBuy", amount); - - quoteResponse.Add("success", true); - quoteResponse.Add("currency", currencyResponse); - quoteResponse.Add("confirm", "asdfad9fj39ma9fj"); - - returnval.Value = quoteResponse; - return returnval; - } - - - quoteResponse.Add("success", false); - quoteResponse.Add("errorMessage", "Invalid parameters passed to the quote box"); - quoteResponse.Add("errorURI", "http://www.opensimulator.org/wiki"); - returnval.Value = quoteResponse; - return returnval; - } - - public XmlRpcResponse buy_func(XmlRpcRequest request) - { - Hashtable requestData = (Hashtable) request.Params[0]; - UUID agentId = UUID.Zero; - int amount = 0; - if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) - { - UUID.TryParse((string) requestData["agentId"], out agentId); - try - { - amount = (Int32) requestData["currencyBuy"]; - } - catch (InvalidCastException) - { - } - if (agentId != UUID.Zero) - { - lock (m_KnownClientFunds) - { - if (m_KnownClientFunds.ContainsKey(agentId)) - { - m_KnownClientFunds[agentId] += amount; - } - else - { - m_KnownClientFunds.Add(agentId, amount); - } - } - IClientAPI client = LocateClientObject(agentId); - if (client != null) - { - SendMoneyBalance(client, agentId, client.SessionId, UUID.Zero); - } - } - } - XmlRpcResponse returnval = new XmlRpcResponse(); - Hashtable returnresp = new Hashtable(); - returnresp.Add("success", true); - returnval.Value = returnresp; - return returnval; - } - - public XmlRpcResponse preflightBuyLandPrep_func(XmlRpcRequest request) - { - XmlRpcResponse ret = new XmlRpcResponse(); - Hashtable retparam = new Hashtable(); - Hashtable membershiplevels = new Hashtable(); - ArrayList levels = new ArrayList(); - Hashtable level = new Hashtable(); - level.Add("id", "00000000-0000-0000-0000-000000000000"); - level.Add("description", "some level"); - levels.Add(level); - //membershiplevels.Add("levels",levels); - - Hashtable landuse = new Hashtable(); - landuse.Add("upgrade", false); - landuse.Add("action", "http://invaliddomaininvalid.com/"); - - Hashtable currency = new Hashtable(); - currency.Add("estimatedCost", 0); - - Hashtable membership = new Hashtable(); - membershiplevels.Add("upgrade", false); - membershiplevels.Add("action", "http://invaliddomaininvalid.com/"); - membershiplevels.Add("levels", membershiplevels); - - retparam.Add("success", true); - retparam.Add("currency", currency); - retparam.Add("membership", membership); - retparam.Add("landuse", landuse); - retparam.Add("confirm", "asdfajsdkfjasdkfjalsdfjasdf"); - - ret.Value = retparam; - - return ret; - } - - public XmlRpcResponse landBuy_func(XmlRpcRequest request) - { - XmlRpcResponse ret = new XmlRpcResponse(); - Hashtable retparam = new Hashtable(); - Hashtable requestData = (Hashtable) request.Params[0]; - - UUID agentId = UUID.Zero; - int amount = 0; - if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) - { - UUID.TryParse((string) requestData["agentId"], out agentId); - try - { - amount = (Int32) requestData["currencyBuy"]; - } - catch (InvalidCastException) - { - } - if (agentId != UUID.Zero) - { - lock (m_KnownClientFunds) - { - if (m_KnownClientFunds.ContainsKey(agentId)) - { - m_KnownClientFunds[agentId] += amount; - } - else - { - m_KnownClientFunds.Add(agentId, amount); - } - } - IClientAPI client = LocateClientObject(agentId); - if (client != null) - { - SendMoneyBalance(client, agentId, client.SessionId, UUID.Zero); - } - } - } - retparam.Add("success", true); - ret.Value = retparam; - - return ret; - } - - #endregion - - #region local Fund Management - - /// - /// Ensures that the agent accounting data is set up in this instance. - /// - /// - private void CheckExistAndRefreshFunds(UUID agentID) - { - lock (m_KnownClientFunds) - { - if (!m_KnownClientFunds.ContainsKey(agentID)) - { - m_KnownClientFunds.Add(agentID, m_stipend); - } - else - { - if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh) - { - m_KnownClientFunds[agentID] = m_stipend; - } - } - } - } - - /// - /// Gets the amount of Funds for an agent - /// - /// - /// - private int GetFundsForAgentID(UUID AgentID) - { - int returnfunds = 0; - lock (m_KnownClientFunds) - { - if (m_KnownClientFunds.ContainsKey(AgentID)) - { - returnfunds = m_KnownClientFunds[AgentID]; - } - else - { - //throw new Exception("Unable to get funds."); - } - } - return returnfunds; - } - - private void SetLocalFundsForAgentID(UUID AgentID, int amount) - { - lock (m_KnownClientFunds) - { - if (m_KnownClientFunds.ContainsKey(AgentID)) - { - m_KnownClientFunds[AgentID] = amount; - } - else - { - m_KnownClientFunds.Add(AgentID, amount); - } - } - } - - #endregion - - #region Utility Helpers - - /// - /// Locates a IClientAPI for the client specified - /// - /// - /// - private IClientAPI LocateClientObject(UUID AgentID) - { - ScenePresence tPresence = null; - IClientAPI rclient = null; - - lock (m_scenel) - { - foreach (Scene _scene in m_scenel.Values) - { - tPresence = _scene.GetScenePresence(AgentID); - if (tPresence != null) - { - if (!tPresence.IsChildAgent) - { - rclient = tPresence.ControllingClient; - } - } - if (rclient != null) - { - return rclient; - } - } - } - return null; - } - - private Scene LocateSceneClientIn(UUID AgentId) - { - lock (m_scenel) - { - foreach (Scene _scene in m_scenel.Values) - { - ScenePresence tPresence = _scene.GetScenePresence(AgentId); - if (tPresence != null) - { - if (!tPresence.IsChildAgent) - { - return _scene; - } - } - } - } - return null; - } - - /// - /// Utility function Gets a Random scene in the instance. For when which scene exactly you're doing something with doesn't matter - /// - /// - public Scene GetRandomScene() - { - lock (m_scenel) - { - foreach (Scene rs in m_scenel.Values) - return rs; - } - return null; - } - - /// - /// Utility function to get a Scene by RegionID in a module - /// - /// - /// - public Scene GetSceneByUUID(UUID RegionID) - { - lock (m_scenel) - { - foreach (Scene rs in m_scenel.Values) - { - if (rs.RegionInfo.originRegionID == RegionID) - { - return rs; - } - } - } - return null; - } - - #endregion - - #region event Handlers - - public void requestPayPrice(IClientAPI client, UUID objectID) - { - Scene scene = LocateSceneClientIn(client.AgentId); - if (scene == null) - return; - - SceneObjectPart task = scene.GetSceneObjectPart(objectID); - if (task == null) - return; - SceneObjectGroup group = task.ParentGroup; - SceneObjectPart root = group.RootPart; - - client.SendPayPrice(objectID, root.PayPrice); - } - - /// - /// When the client closes the connection we remove their accounting info from memory to free up resources. - /// - /// - public void ClientClosed(UUID AgentID) - { - lock (m_KnownClientFunds) - { - if (m_keepMoneyAcrossLogins && m_MoneyAddress.Length == 0) - { - } - else - { - m_KnownClientFunds.Remove(AgentID); - } - } - } - - /// - /// Event called Economy Data Request handler. - /// - /// - public void EconomyDataRequestHandler(UUID agentId) - { - IClientAPI user = LocateClientObject(agentId); - - if (user != null) - { - user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, - PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, - PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload, - TeleportMinPrice, TeleportPriceExponent); - } - } - - private void ValidateLandBuy(Object osender, EventManager.LandBuyArgs e) - { - if (m_MoneyAddress.Length == 0) - { - lock (m_KnownClientFunds) - { - if (m_KnownClientFunds.ContainsKey(e.agentId)) - { - // Does the sender have enough funds to give? - if (m_KnownClientFunds[e.agentId] >= e.parcelPrice) - { - lock (e) - { - e.economyValidated = true; - } - } - } - } - } - else - { - if (GetRemoteBalance(e.agentId) >= e.parcelPrice) - { - lock (e) - { - e.economyValidated = true; - } - } - } - } - - private void processLandBuy(Object osender, EventManager.LandBuyArgs e) - { - lock (e) - { - if (e.economyValidated == true && e.transactionID == 0) - { - e.transactionID = Util.UnixTimeSinceEpoch(); - - if (doMoneyTransfer(e.agentId, e.parcelOwnerID, e.parcelPrice, 0, "Land purchase")) - { - lock (e) - { - e.amountDebited = e.parcelPrice; - } - } - } - } - } - - /// - /// THis method gets called when someone pays someone else as a gift. - /// - /// - /// - private void MoneyTransferAction(Object osender, EventManager.MoneyTransferArgs e) - { - IClientAPI sender = null; - IClientAPI receiver = null; - - if (m_MoneyAddress.Length > 0) // Handled on server - e.description = String.Empty; - - if (e.transactiontype == 5008) // Object gets paid - { - sender = LocateClientObject(e.sender); - if (sender != null) - { - SceneObjectPart part = findPrim(e.receiver); - if (part == null) - return; - - string name = resolveAgentName(part.OwnerID); - if (name == String.Empty) - name = "(hippos)"; - - receiver = LocateClientObject(part.OwnerID); - - string description = String.Format("Paid {0} via object {1}", name, e.description); - bool transactionresult = doMoneyTransfer(e.sender, part.OwnerID, e.amount, e.transactiontype, description); - - if (transactionresult) - { - ObjectPaid handlerOnObjectPaid = OnObjectPaid; - if (handlerOnObjectPaid != null) - { - handlerOnObjectPaid(e.receiver, e.sender, e.amount); - } - } - - if (e.sender != e.receiver) - { - sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.sender)); - } - if (receiver != null) - { - receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(part.OwnerID)); - } - } - return; - } - - sender = LocateClientObject(e.sender); - if (sender != null) - { - receiver = LocateClientObject(e.receiver); - - bool transactionresult = doMoneyTransfer(e.sender, e.receiver, e.amount, e.transactiontype, e.description); - - if (e.sender != e.receiver) - { - if (sender != null) - { - sender.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.sender)); - } - } - - if (receiver != null) - { - receiver.SendMoneyBalance(UUID.Random(), transactionresult, Utils.StringToBytes(e.description), GetFundsForAgentID(e.receiver)); - } - } - else - { - m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" + - e.sender.ToString() + " Receiver: " + e.receiver.ToString() + " Amount: " + e.amount.ToString()); - } - } - - /// - /// Event Handler for when a root agent becomes a child agent - /// - /// - private void MakeChildAgent(ScenePresence avatar) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - if (m_rootAgents[avatar.UUID] == avatar.Scene.RegionInfo.originRegionID) - { - m_rootAgents.Remove(avatar.UUID); -// m_log.Debug("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); - } - } - } - } - - /// - /// Event Handler for when the client logs out. - /// - /// - private void ClientLoggedOut(UUID AgentId) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(AgentId)) - { - m_rootAgents.Remove(AgentId); - //m_log.Info("[MONEY]: Removing " + AgentId + ". Agent logged out."); - } - } - } - - /// - /// Call this when the client disconnects. - /// - /// - public void ClientClosed(IClientAPI client) - { - ClientClosed(client.AgentId); - } - - /// - /// Event Handler for when an Avatar enters one of the parcels in the simulator. - /// - /// - /// - /// - private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - if (avatar.Scene.RegionInfo.originRegionID != m_rootAgents[avatar.UUID]) - { - m_rootAgents[avatar.UUID] = avatar.Scene.RegionInfo.originRegionID; - - - //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); - // Claim User! my user! Mine mine mine! - if (m_MoneyAddress.Length > 0) - { - Scene RegionItem = GetSceneByUUID(regionID); - if (RegionItem != null) - { - Hashtable hresult = - claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret); - if ((bool)hresult["success"] == true) - { - int funds = 0; - try - { - funds = (Int32)hresult["funds"]; - } - catch (InvalidCastException) - { - } - SetLocalFundsForAgentID(avatar.UUID, funds); - } - else - { - avatar.ControllingClient.SendAgentAlertMessage((string)hresult["errorMessage"], true); - } - } - } - } - else - { - ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); - if ((obj.landData.Flags & (uint)Parcel.ParcelFlags.AllowDamage) != 0) - { - avatar.Invulnerable = false; - } - else - { - avatar.Invulnerable = true; - } - } - } - else - { - lock (m_rootAgents) - { - m_rootAgents.Add(avatar.UUID, avatar.Scene.RegionInfo.originRegionID); - } - if (m_MoneyAddress.Length > 0) - { - Scene RegionItem = GetSceneByUUID(regionID); - if (RegionItem != null) - { - Hashtable hresult = claim_user(avatar.UUID, avatar.ControllingClient.SecureSessionId, regionID, RegionItem.RegionInfo.regionSecret); - if ((bool) hresult["success"] == true) - { - int funds = 0; - try - { - funds = (Int32) hresult["funds"]; - } - catch (InvalidCastException) - { - } - SetLocalFundsForAgentID(avatar.UUID, funds); - } - else - { - avatar.ControllingClient.SendAgentAlertMessage((string) hresult["errorMessage"], true); - } - } - } - - //m_log.Info("[MONEY]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); - } - } - //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); - } - - public int GetBalance(IClientAPI client) - { - GetClientFunds(client); - - lock (m_KnownClientFunds) - { - if (!m_KnownClientFunds.ContainsKey(client.AgentId)) - return 0; - - return m_KnownClientFunds[client.AgentId]; - } - } - - // Please do not refactor these to be just one method - // Existing implementations need the distinction - // - public bool UploadCovered(IClientAPI client) - { - return AmountCovered(client, PriceUpload); - } - - public bool GroupCreationCovered(IClientAPI client) - { - return AmountCovered(client, PriceGroupCreate); - } - - public bool AmountCovered(IClientAPI client, int amount) - { - if (GetBalance(client) < amount) - return false; - return true; - } - - #endregion - - public void ObjectBuy(IClientAPI remoteClient, UUID agentID, - UUID sessionID, UUID groupID, UUID categoryID, - uint localID, byte saleType, int salePrice) - { - GetClientFunds(remoteClient); - - if (!m_KnownClientFunds.ContainsKey(remoteClient.AgentId)) - { - remoteClient.SendAgentAlertMessage("Unable to buy now. Your account balance was not found.", false); - return; - } - - int funds = m_KnownClientFunds[remoteClient.AgentId]; - - if (salePrice != 0 && funds < salePrice) - { - remoteClient.SendAgentAlertMessage("Unable to buy now. You don't have sufficient funds.", false); - return; - } - - Scene s = LocateSceneClientIn(remoteClient.AgentId); - - SceneObjectPart part = s.GetSceneObjectPart(localID); - if (part == null) - { - remoteClient.SendAgentAlertMessage("Unable to buy now. The object was not found.", false); - return; - } - - if (s.PerformObjectBuy(remoteClient, categoryID, localID, saleType)) - doMoneyTransfer(remoteClient.AgentId, part.OwnerID, salePrice, 5000, "Object buy"); - } - } - - public enum TransactionType : int - { - SystemGenerated = 0, - RegionMoneyRequest = 1, - Gift = 2, - Purchase = 3 - } - - -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs deleted file mode 100644 index d3ac2c0..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Dialog/DialogModule.cs +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Dialog -{ - public class DialogModule : IRegionModule, IDialogModule - { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() {} - public void Close() {} - public string Name { get { return "Dialog Module"; } } - public bool IsSharedModule { get { return false; } } - - public void SendAlertToUser(IClientAPI client, string message) - { - SendAlertToUser(client, message, false); - } - - public void SendAlertToUser(IClientAPI client, string message, bool modal) - { - client.SendAgentAlertMessage(message, modal); - } - - public void SendAlertToUser(UUID agentID, string message) - { - SendAlertToUser(agentID, message, false); - } - - public void SendAlertToUser(UUID agentID, string message, bool modal) - { - ScenePresence sp = m_scene.GetScenePresence(agentID); - - if (sp != null) - sp.ControllingClient.SendAgentAlertMessage(message, modal); - } - - public void SendAlertToUser(string firstName, string lastName, string message, bool modal) - { - List presenceList = m_scene.GetScenePresences(); - - foreach (ScenePresence presence in presenceList) - { - if (presence.Firstname == firstName && presence.Lastname == lastName) - { - presence.ControllingClient.SendAgentAlertMessage(message, modal); - break; - } - } - } - - public void SendGeneralAlert(string message) - { - List presenceList = m_scene.GetScenePresences(); - - foreach (ScenePresence presence in presenceList) - { - if (!presence.IsChildAgent) - presence.ControllingClient.SendAlertMessage(message); - } - } - - public void SendDialogToUser( - UUID avatarID, string objectName, UUID objectID, UUID ownerID, - string message, UUID textureID, int ch, string[] buttonlabels) - { - ScenePresence sp = m_scene.GetScenePresence(avatarID); - - if (sp != null) - sp.ControllingClient.SendDialog(objectName, objectID, ownerID, message, textureID, ch, buttonlabels); - } - - public void SendUrlToUser( - UUID avatarID, string objectName, UUID objectID, UUID ownerID, bool groupOwned, string message, string url) - { - ScenePresence sp = m_scene.GetScenePresence(avatarID); - - if (sp != null) - sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); - } - - public void SendNotificationToUsersInEstate( - UUID fromAvatarID, string fromAvatarName, string message) - { - // TODO: This does not yet do what it says on the tin - it only sends the message to users in the same - // region as the sending avatar. - SendNotificationToUsersInRegion(fromAvatarID, fromAvatarName, message); - } - - public void SendNotificationToUsersInRegion( - UUID fromAvatarID, string fromAvatarName, string message) - { - List presenceList = m_scene.GetScenePresences(); - - foreach (ScenePresence presence in presenceList) - { - if (!presence.IsChildAgent) - presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs deleted file mode 100644 index 0ed962e..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs +++ /dev/null @@ -1,1003 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Friends -{ - /* - This module handles adding/removing friends, and the the presence - notification process for login/logoff of friends. - - The presence notification works as follows: - - After the user initially connects to a region (so we now have a UDP - connection to work with), this module fetches the friends of user - (those are cached), their on-/offline status, and info about the - region they are in from the MessageServer. - - (*) It then informs the user about the on-/offline status of her friends. - - It then informs all online friends currently on this region-server about - user's new online status (this will save some network traffic, as local - messages don't have to be transferred inter-region, and it will be all - that has to be done in Standalone Mode). - - For the rest of the online friends (those not on this region-server), - this module uses the provided region-information to map users to - regions, and sends one notification to every region containing the - friends to inform on that server. - - The region-server will handle that in the following way: - - If it finds the friend, it informs her about the user being online. - - If it doesn't find the friend (maybe she TPed away in the meantime), - it stores that information. - - After it processed all friends, it returns the list of friends it - couldn't find. - - If this list isn't empty, the FriendsModule re-requests information - about those online friends that have been missed and starts at (*) - again until all friends have been found, or until it tried 3 times - (to prevent endless loops due to some uncaught error). - - NOTE: Online/Offline notifications don't need to be sent on region change. - - We implement two XMLRpc handlers here, handling all the inter-region things - we have to handle: - - On-/Offline-Notifications (bulk) - - Terminate Friendship messages (single) - */ - - public class FriendsModule : IRegionModule, IFriendsModule - { - private class Transaction - { - public UUID agentID; - public string agentName; - public uint count; - - public Transaction(UUID agentID, string agentName) - { - this.agentID = agentID; - this.agentName = agentName; - this.count = 1; - } - } - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Cache m_friendLists = new Cache(CacheFlags.AllowUpdate); - - private Dictionary m_rootAgents = new Dictionary(); - - private Dictionary m_pendingCallingcardRequests = new Dictionary(); - - private Scene m_initialScene; // saves a lookup if we don't have a specific scene - private Dictionary m_scenes = new Dictionary(); - private IMessageTransferModule m_TransferModule = null; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - lock (m_scenes) - { - if (m_scenes.Count == 0) - { - scene.CommsManager.HttpServer.AddXmlRPCHandler("presence_update_bulk", processPresenceUpdateBulk); - scene.CommsManager.HttpServer.AddXmlRPCHandler("terminate_friend", processTerminateFriend); - m_friendLists.DefaultTTL = new TimeSpan(1, 0, 0); // store entries for one hour max - m_initialScene = scene; - } - - if (!m_scenes.ContainsKey(scene.RegionInfo.RegionHandle)) - m_scenes[scene.RegionInfo.RegionHandle] = scene; - } - - scene.RegisterModuleInterface(this); - - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; - scene.EventManager.OnClientClosed += ClientClosed; - } - - public void PostInitialise() - { - if (m_scenes.Count > 0) - { - m_TransferModule = m_initialScene.RequestModuleInterface(); - } - if (m_TransferModule == null) - m_log.Error("[FRIENDS]: Unable to find a message transfer module, friendship offers will not work"); - } - - public void Close() - { - } - - public string Name - { - get { return "FriendsModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - /// - /// Receive presence information changes about clients in other regions. - /// - /// - /// - public XmlRpcResponse processPresenceUpdateBulk(XmlRpcRequest req) - { - Hashtable requestData = (Hashtable)req.Params[0]; - - List friendsNotHere = new List(); - - // this is called with the expectation that all the friends in the request are on this region-server. - // But as some time passed since we checked (on the other region-server, via the MessagingServer), - // some of the friends might have teleported away. - // Actually, even now, between this line and the sending below, some people could TP away. So, - // we'll have to lock the m_rootAgents list for the duration to prevent/delay that. - lock (m_rootAgents) - { - List friendsHere = new List(); - - try - { - UUID agentID = new UUID((string)requestData["agentID"]); - bool agentOnline = (bool)requestData["agentOnline"]; - int count = (int)requestData["friendCount"]; - for (int i = 0; i < count; ++i) - { - UUID uuid; - if (UUID.TryParse((string)requestData["friendID_" + i], out uuid)) - { - if (m_rootAgents.ContainsKey(uuid)) friendsHere.Add(GetRootPresenceFromAgentID(uuid)); - else friendsNotHere.Add(uuid); - } - } - - // now send, as long as they are still here... - UUID[] agentUUID = new UUID[] { agentID }; - if (agentOnline) - { - foreach (ScenePresence agent in friendsHere) - { - agent.ControllingClient.SendAgentOnline(agentUUID); - } - } - else - { - foreach (ScenePresence agent in friendsHere) - { - agent.ControllingClient.SendAgentOffline(agentUUID); - } - } - } - catch(Exception e) - { - m_log.Warn("[FRIENDS]: Got exception while parsing presence_update_bulk request:", e); - } - } - - // no need to lock anymore; if TPs happen now, worst case is that we have an additional agent in this region, - // which should be caught on the next iteration... - Hashtable result = new Hashtable(); - int idx = 0; - foreach (UUID uuid in friendsNotHere) - { - result["friendID_" + idx++] = uuid.ToString(); - } - result["friendCount"] = idx; - - XmlRpcResponse response = new XmlRpcResponse(); - response.Value = result; - - return response; - } - - public XmlRpcResponse processTerminateFriend(XmlRpcRequest req) - { - Hashtable requestData = (Hashtable)req.Params[0]; - - bool success = false; - - UUID agentID; - UUID friendID; - if (requestData.ContainsKey("agentID") && UUID.TryParse((string)requestData["agentID"], out agentID) && - requestData.ContainsKey("friendID") && UUID.TryParse((string)requestData["friendID"], out friendID)) - { - // try to find it and if it is there, prevent it to vanish before we sent the message - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(agentID)) - { - m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", friendID, agentID); - GetRootPresenceFromAgentID(agentID).ControllingClient.SendTerminateFriend(friendID); - success = true; - } - } - } - - // return whether we were successful - Hashtable result = new Hashtable(); - result["success"] = success; - - XmlRpcResponse response = new XmlRpcResponse(); - response.Value = result; - return response; - } - - private void OnNewClient(IClientAPI client) - { - // All friends establishment protocol goes over instant message - // There's no way to send a message from the sim - // to a user to 'add a friend' without causing dialog box spam - - // Subscribe to instant messages - client.OnInstantMessage += OnInstantMessage; - - // Friend list management - client.OnApproveFriendRequest += OnApproveFriendRequest; - client.OnDenyFriendRequest += OnDenyFriendRequest; - client.OnTerminateFriendship += OnTerminateFriendship; - - // ... calling card handling... - client.OnOfferCallingCard += OnOfferCallingCard; - client.OnAcceptCallingCard += OnAcceptCallingCard; - client.OnDeclineCallingCard += OnDeclineCallingCard; - - // we need this one exactly once per agent session (see comments in the handler below) - client.OnEconomyDataRequest += OnEconomyDataRequest; - - // if it leaves, we want to know, too - client.OnLogout += OnLogout; - } - - private void ClientClosed(UUID AgentId) - { - // agent's client was closed. As we handle logout in OnLogout, this here has only to handle - // TPing away (root agent is closed) or TPing/crossing in a region far enough away (client - // agent is closed). - // NOTE: In general, this doesn't mean that the agent logged out, just that it isn't around - // in one of the regions here anymore. - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(AgentId)) - { - m_rootAgents.Remove(AgentId); - } - } - } - - private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) - { - lock (m_rootAgents) - { - m_rootAgents[avatar.UUID] = avatar.RegionHandle; - // Claim User! my user! Mine mine mine! - } - } - - private void MakeChildAgent(ScenePresence avatar) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - // only delete if the region matches. As this is a shared module, the avatar could be - // root agent in another region on this server. - if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) - { - m_rootAgents.Remove(avatar.UUID); -// m_log.Debug("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); - } - } - } - } - - private ScenePresence GetRootPresenceFromAgentID(UUID AgentID) - { - ScenePresence returnAgent = null; - lock (m_scenes) - { - ScenePresence queryagent = null; - foreach (Scene scene in m_scenes.Values) - { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) - { - if (!queryagent.IsChildAgent) - { - returnAgent = queryagent; - break; - } - } - } - } - return returnAgent; - } - - private ScenePresence GetAnyPresenceFromAgentID(UUID AgentID) - { - ScenePresence returnAgent = null; - lock (m_scenes) - { - ScenePresence queryagent = null; - foreach (Scene scene in m_scenes.Values) - { - queryagent = scene.GetScenePresence(AgentID); - if (queryagent != null) - { - returnAgent = queryagent; - break; - } - } - } - return returnAgent; - } - - public void OfferFriendship(UUID fromUserId, IClientAPI toUserClient, string offerMessage) - { - CachedUserInfo userInfo = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(fromUserId); - - if (userInfo != null) - { - GridInstantMessage msg = new GridInstantMessage( - toUserClient.Scene, fromUserId, userInfo.UserProfile.Name, toUserClient.AgentId, - (byte)InstantMessageDialog.FriendshipOffered, offerMessage, false, Vector3.Zero); - - FriendshipOffered(msg); - } - else - { - m_log.ErrorFormat("[FRIENDS]: No user found for id {0} in OfferFriendship()", fromUserId); - } - } - - #region FriendRequestHandling - - private void OnInstantMessage(IClientAPI client, GridInstantMessage im) - { - // Friend Requests go by Instant Message.. using the dialog param - // https://wiki.secondlife.com/wiki/ImprovedInstantMessage - - if (im.dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38 - { - // fromAgentName is the *destination* name (the friend we offer friendship to) - ScenePresence initiator = GetAnyPresenceFromAgentID(new UUID(im.fromAgentID)); - im.fromAgentName = initiator != null ? initiator.Name : "(hippo)"; - - FriendshipOffered(im); - } - else if (im.dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39 - { - FriendshipAccepted(client, im); - } - else if (im.dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40 - { - FriendshipDeclined(client, im); - } - } - - /// - /// Invoked when a user offers a friendship. - /// - /// - /// - /// - private void FriendshipOffered(GridInstantMessage im) - { - // this is triggered by the initiating agent: - // A local agent offers friendship to some possibly remote friend. - // A IM is triggered, processed here and sent to the friend (possibly in a remote region). - - m_log.DebugFormat("[FRIEND]: Offer(38) - From: {0}, FromName: {1} To: {2}, Session: {3}, Message: {4}, Offline {5}", - im.fromAgentID, im.fromAgentName, im.toAgentID, im.imSessionID, im.message, im.offline); - - // 1.20 protocol sends an UUID in the message field, instead of the friendship offer text. - // For interoperability, we have to clear that - if (Util.isUUID(im.message)) im.message = ""; - - // be sneeky and use the initiator-UUID as transactionID. This means we can be stateless. - // we have to look up the agent name on friendship-approval, though. - im.imSessionID = im.fromAgentID; - - if (m_TransferModule != null) - { - // Send it to whoever is the destination. - // If new friend is local, it will send an IM to the viewer. - // If new friend is remote, it will cause a OnGridInstantMessage on the remote server - m_TransferModule.SendInstantMessage( - im, - delegate(bool success) - { - m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); - } - ); - } - } - - /// - /// Invoked when a user accepts a friendship offer. - /// - /// - /// - private void FriendshipAccepted(IClientAPI client, GridInstantMessage im) - { - m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {2} {3}, imsession {4} to {5}: {6} (dialog {7})", - client.AgentId, im.fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog); - } - - /// - /// Invoked when a user declines a friendship offer. - /// - /// May not currently be used - see OnDenyFriendRequest() instead - /// - /// - private void FriendshipDeclined(IClientAPI client, GridInstantMessage im) - { - UUID fromAgentID = new UUID(im.fromAgentID); - UUID toAgentID = new UUID(im.toAgentID); - - // declining the friendship offer causes a type 40 IM being sent to the (possibly remote) initiator - // toAgentID is initiator, fromAgentID declined friendship - m_log.DebugFormat("[FRIEND]: 40 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})", - client != null ? client.AgentId.ToString() : "", - fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog); - - // Send the decline to whoever is the destination. - GridInstantMessage msg - = new GridInstantMessage( - client.Scene, fromAgentID, client.Name, toAgentID, - im.dialog, im.message, im.offline != 0, im.Position); - - // If new friend is local, it will send an IM to the viewer. - // If new friend is remote, it will cause a OnGridInstantMessage on the remote server - m_TransferModule.SendInstantMessage(msg, - delegate(bool success) { - m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); - } - ); - } - - private void OnGridInstantMessage(GridInstantMessage msg) - { - // This event won't be raised unless we have that agent, - // so we can depend on the above not trying to send - // via grid again - m_log.DebugFormat("[FRIEND]: Got GridIM from {0}, to {1}, imSession {2}, message {3}, dialog {4}", - msg.fromAgentID, msg.toAgentID, msg.imSessionID, msg.message, msg.dialog); - - if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered || - msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted || - msg.dialog == (byte)InstantMessageDialog.FriendshipDeclined) - { - // this should succeed as we *know* the root agent is here. - m_TransferModule.SendInstantMessage(msg, - delegate(bool success) { - m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); - } - ); - } - - if (msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted) - { - // for accept friendship, we have to do a bit more - ApproveFriendship(new UUID(msg.fromAgentID), new UUID(msg.toAgentID), msg.fromAgentName); - } - } - - private void ApproveFriendship(UUID fromAgentID, UUID toAgentID, string fromName) - { - m_log.DebugFormat("[FRIEND]: Approve friendship from {0} (ID: {1}) to {2}", - fromAgentID, fromName, toAgentID); - - // a new friend was added in the initiator's and friend's data, so the cache entries are wrong now. - lock (m_friendLists) - { - m_friendLists.Invalidate(fromAgentID); - m_friendLists.Invalidate(toAgentID); - } - - // now send presence update and add a calling card for the new friend - - ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID); - if (initiator == null) - { - // quite wrong. Shouldn't happen. - m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID); - return; - } - - m_log.DebugFormat("[FRIEND]: Tell {0} that {1} is online", - initiator.Name, fromName); - // tell initiator that friend is online - initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID }); - - // find the folder for the friend... - InventoryFolderImpl folder = - initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard); - if (folder != null) - { - // ... and add the calling card - CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromName); - } - } - - private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) - { - m_log.DebugFormat("[FRIEND]: Got approve friendship from {0} {1}, agentID {2}, tid {3}", - client.Name, client.AgentId, agentID, friendID); - - // store the new friend persistently for both avatars - m_initialScene.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline); - - // The cache entries aren't valid anymore either, as we just added a friend to both sides. - lock (m_friendLists) - { - m_friendLists.Invalidate(agentID); - m_friendLists.Invalidate(friendID); - } - - // if it's a local friend, we don't have to do the lookup - ScenePresence friendPresence = GetAnyPresenceFromAgentID(friendID); - - if (friendPresence != null) - { - m_log.Debug("[FRIEND]: Local agent detected."); - - // create calling card - CreateCallingCard(client, friendID, callingCardFolders[0], friendPresence.Name); - - // local message means OnGridInstantMessage won't be triggered, so do the work here. - friendPresence.ControllingClient.SendInstantMessage(agentID, agentID.ToString(), friendID, client.Name, - (byte)InstantMessageDialog.FriendshipAccepted, - (uint)Util.UnixTimeSinceEpoch()); - ApproveFriendship(agentID, friendID, client.Name); - } - else - { - m_log.Debug("[FRIEND]: Remote agent detected."); - - // fetch the friend's name for the calling card. - CachedUserInfo info = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(friendID); - - // create calling card - CreateCallingCard(client, friendID, callingCardFolders[0], - info.UserProfile.FirstName + " " + info.UserProfile.SurName); - - // Compose (remote) response to friend. - GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID, - (byte)InstantMessageDialog.FriendshipAccepted, - agentID.ToString(), false, Vector3.Zero); - if (m_TransferModule != null) - { - m_TransferModule.SendInstantMessage(msg, - delegate(bool success) { - m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); - } - ); - } - } - - // tell client that new friend is online - client.SendAgentOnline(new UUID[] { friendID }); - } - - private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) - { - m_log.DebugFormat("[FRIEND]: Got deny friendship from {0} {1}, agentID {2}, tid {3}", - client.Name, client.AgentId, agentID, friendID); - - // Compose response to other agent. - GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID, - (byte)InstantMessageDialog.FriendshipDeclined, - agentID.ToString(), false, Vector3.Zero); - // send decline to initiator - if (m_TransferModule != null) - { - m_TransferModule.SendInstantMessage(msg, - delegate(bool success) { - m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success); - } - ); - } - } - - private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) - { - // client.AgentId == agentID! - - // this removes the friends from the stored friendlists. After the next login, they will be gone... - m_initialScene.StoreRemoveFriendship(agentID, exfriendID); - - // ... now tell the two involved clients that they aren't friends anymore. - - // I don't know why we have to tell , as this was caused by her, but that's how it works in SL... - client.SendTerminateFriend(exfriendID); - - // now send the friend, if online - ScenePresence presence = GetAnyPresenceFromAgentID(exfriendID); - if (presence != null) - { - m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", agentID, exfriendID); - presence.ControllingClient.SendTerminateFriend(agentID); - } - else - { - // retry 3 times, in case the agent TPed from the last known region... - for (int retry = 0; retry < 3; ++retry) - { - // wasn't sent, so ex-friend wasn't around on this region-server. Fetch info and try to send - UserAgentData data = m_initialScene.CommsManager.UserService.GetAgentByUUID(exfriendID); - - if (null == data) - break; - - if (!data.AgentOnline) - { - m_log.DebugFormat("[FRIEND]: {0} is offline, so not sending TerminateFriend", exfriendID); - break; // if ex-friend isn't online, we don't need to send - } - - m_log.DebugFormat("[FRIEND]: Sending remote terminate friend {0} to agent {1}@{2}", - agentID, exfriendID, data.Handle); - - // try to send to foreign region, retry if it fails (friend TPed away, for example) - if (m_initialScene.TriggerTerminateFriend(data.Handle, exfriendID, agentID)) break; - } - } - - // clean up cache: FriendList is wrong now... - lock (m_friendLists) - { - m_friendLists.Invalidate(agentID); - m_friendLists.Invalidate(exfriendID); - } - } - - #endregion - - #region CallingCards - - private void OnOfferCallingCard(IClientAPI client, UUID destID, UUID transactionID) - { - m_log.DebugFormat("[CALLING CARD]: got offer from {0} for {1}, transaction {2}", - client.AgentId, destID, transactionID); - // This might be slightly wrong. On a multi-region server, we might get the child-agent instead of the root-agent - // (or the root instead of the child) - ScenePresence destAgent = GetAnyPresenceFromAgentID(destID); - if (destAgent == null) - { - client.SendAlertMessage("The person you have offered a card to can't be found anymore."); - return; - } - - lock (m_pendingCallingcardRequests) - { - m_pendingCallingcardRequests[transactionID] = client.AgentId; - } - // inform the destination agent about the offer - destAgent.ControllingClient.SendOfferCallingCard(client.AgentId, transactionID); - } - - private void CreateCallingCard(IClientAPI client, UUID creator, UUID folder, string name) - { - InventoryItemBase item = new InventoryItemBase(); - item.AssetID = UUID.Zero; - item.AssetType = (int)AssetType.CallingCard; - item.BasePermissions = (uint)PermissionMask.Copy; - item.CreationDate = Util.UnixTimeSinceEpoch(); - item.Creator = creator; - item.CurrentPermissions = item.BasePermissions; - item.Description = ""; - item.EveryOnePermissions = (uint)PermissionMask.None; - item.Flags = 0; - item.Folder = folder; - item.GroupID = UUID.Zero; - item.GroupOwned = false; - item.ID = UUID.Random(); - item.InvType = (int)InventoryType.CallingCard; - item.Name = name; - item.NextPermissions = item.EveryOnePermissions; - item.Owner = client.AgentId; - item.SalePrice = 10; - item.SaleType = (byte)SaleType.Not; - ((Scene)client.Scene).AddInventoryItem(client, item); - } - - private void OnAcceptCallingCard(IClientAPI client, UUID transactionID, UUID folderID) - { - m_log.DebugFormat("[CALLING CARD]: User {0} ({1} {2}) accepted tid {3}, folder {4}", - client.AgentId, - client.FirstName, client.LastName, - transactionID, folderID); - UUID destID; - lock (m_pendingCallingcardRequests) - { - if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID)) - { - m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.", - client.Name); - return; - } - // else found pending calling card request with that transaction. - m_pendingCallingcardRequests.Remove(transactionID); - } - - - ScenePresence destAgent = GetAnyPresenceFromAgentID(destID); - // inform sender of the card that destination declined the offer - if (destAgent != null) destAgent.ControllingClient.SendAcceptCallingCard(transactionID); - - // put a calling card into the inventory of receiver - CreateCallingCard(client, destID, folderID, destAgent.Name); - } - - private void OnDeclineCallingCard(IClientAPI client, UUID transactionID) - { - m_log.DebugFormat("[CALLING CARD]: User {0} (ID:{1}) declined card, tid {2}", - client.Name, client.AgentId, transactionID); - UUID destID; - lock (m_pendingCallingcardRequests) - { - if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID)) - { - m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.", - client.Name); - return; - } - // else found pending calling card request with that transaction. - m_pendingCallingcardRequests.Remove(transactionID); - } - - ScenePresence destAgent = GetAnyPresenceFromAgentID(destID); - // inform sender of the card that destination declined the offer - if (destAgent != null) destAgent.ControllingClient.SendDeclineCallingCard(transactionID); - } - - /// - /// Send presence information about a client to other clients in both this region and others. - /// - /// - /// - /// - private void SendPresenceState(IClientAPI client, List friendList, bool iAmOnline) - { - //m_log.DebugFormat("[FRIEND]: {0} logged {1}; sending presence updates", client.Name, iAmOnline ? "in" : "out"); - - if (friendList == null || friendList.Count == 0) - { - //m_log.DebugFormat("[FRIEND]: {0} doesn't have friends.", client.Name); - return; // nothing we can do if she doesn't have friends... - } - - // collect sets of friendIDs; to send to (online and offline), and to receive from - // TODO: If we ever switch to .NET >= 3, replace those Lists with HashSets. - // I can't believe that we have Dictionaries, but no Sets, considering Java introduced them years ago... - List friendIDsToSendTo = new List(); - List candidateFriendIDsToReceive = new List(); - - foreach (FriendListItem item in friendList) - { - if (((item.FriendListOwnerPerms | item.FriendPerms) & (uint)FriendRights.CanSeeOnline) != 0) - { - // friend is allowed to see my presence => add - if ((item.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0) - friendIDsToSendTo.Add(item.Friend); - - if ((item.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0) - candidateFriendIDsToReceive.Add(item.Friend); - } - } - - // we now have a list of "interesting" friends (which we have to find out on-/offline state for), - // friends we want to send our online state to (if *they* are online, too), and - // friends we want to receive online state for (currently unknown whether online or not) - - // as this processing might take some time and friends might TP away, we try up to three times to - // reach them. Most of the time, we *will* reach them, and this loop won't loop - int retry = 0; - do - { - // build a list of friends to look up region-information and on-/offline-state for - List friendIDsToLookup = new List(friendIDsToSendTo); - foreach (UUID uuid in candidateFriendIDsToReceive) - { - if (!friendIDsToLookup.Contains(uuid)) friendIDsToLookup.Add(uuid); - } - - m_log.DebugFormat( - "[FRIEND]: {0} to lookup, {1} to send to, {2} candidates to receive from for agent {3}", - friendIDsToLookup.Count, friendIDsToSendTo.Count, candidateFriendIDsToReceive.Count, client.Name); - - // we have to fetch FriendRegionInfos, as the (cached) FriendListItems don't - // necessarily contain the correct online state... - Dictionary friendRegions = m_initialScene.GetFriendRegionInfos(friendIDsToLookup); - m_log.DebugFormat( - "[FRIEND]: Found {0} regionInfos for {1} friends of {2}", - friendRegions.Count, friendIDsToLookup.Count, client.Name); - - // argument for SendAgentOn/Offline; we shouldn't generate that repeatedly within loops. - UUID[] agentArr = new UUID[] { client.AgentId }; - - // first, send to friend presence state to me, if I'm online... - if (iAmOnline) - { - List friendIDsToReceive = new List(); - - for (int i = candidateFriendIDsToReceive.Count - 1; i >= 0; --i) - { - UUID uuid = candidateFriendIDsToReceive[i]; - FriendRegionInfo info; - if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline) - { - friendIDsToReceive.Add(uuid); - } - } - - m_log.DebugFormat( - "[FRIEND]: Sending {0} online friends to {1}", friendIDsToReceive.Count, client.Name); - - if (friendIDsToReceive.Count > 0) - client.SendAgentOnline(friendIDsToReceive.ToArray()); - - // clear them for a possible second iteration; we don't have to repeat this - candidateFriendIDsToReceive.Clear(); - } - - // now, send my presence state to my friends - for (int i = friendIDsToSendTo.Count - 1; i >= 0; --i) - { - UUID uuid = friendIDsToSendTo[i]; - FriendRegionInfo info; - if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline) - { - // any client is good enough, root or child... - ScenePresence agent = GetAnyPresenceFromAgentID(uuid); - if (agent != null) - { - m_log.DebugFormat("[FRIEND]: Found local agent {0}", agent.Name); - - // friend is online and on this server... - if (iAmOnline) agent.ControllingClient.SendAgentOnline(agentArr); - else agent.ControllingClient.SendAgentOffline(agentArr); - - // done, remove it - friendIDsToSendTo.RemoveAt(i); - } - } - else - { - m_log.DebugFormat("[FRIEND]: Friend {0} ({1}) is offline; not sending.", uuid, i); - - // friend is offline => no need to try sending - friendIDsToSendTo.RemoveAt(i); - } - } - - m_log.DebugFormat("[FRIEND]: Have {0} friends to contact via inter-region comms.", friendIDsToSendTo.Count); - - // we now have all the friends left that are online (we think), but not on this region-server - if (friendIDsToSendTo.Count > 0) - { - // sort them into regions - Dictionary> friendsInRegion = new Dictionary>(); - foreach (UUID uuid in friendIDsToSendTo) - { - ulong handle = friendRegions[uuid].regionHandle; // this can't fail as we filtered above already - List friends; - if (!friendsInRegion.TryGetValue(handle, out friends)) - { - friends = new List(); - friendsInRegion[handle] = friends; - } - friends.Add(uuid); - } - m_log.DebugFormat("[FRIEND]: Found {0} regions to send to.", friendRegions.Count); - - // clear uuids list and collect missed friends in it for the next retry - friendIDsToSendTo.Clear(); - - // send bulk updates to the region - foreach (KeyValuePair> pair in friendsInRegion) - { - m_log.DebugFormat("[FRIEND]: Inform {0} friends in region {1} that user {2} is {3}line", - pair.Value.Count, pair.Key, client.Name, iAmOnline ? "on" : "off"); - - friendIDsToSendTo.AddRange(m_initialScene.InformFriendsInOtherRegion(client.AgentId, pair.Key, pair.Value, iAmOnline)); - } - } - // now we have in friendIDsToSendTo only the agents left that TPed away while we tried to contact them. - // In most cases, it will be empty, and it won't loop here. But sometimes, we have to work harder and try again... - } - while (++retry < 3 && friendIDsToSendTo.Count > 0); - } - - private void OnEconomyDataRequest(UUID agentID) - { - // KLUDGE: This is the only way I found to get a message (only) after login was completed and the - // client is connected enough to receive UDP packets). - // This packet seems to be sent only once, just after connection was established to the first - // region after login. - // We use it here to trigger a presence update; the old update-on-login was never be heard by - // the freshly logged in viewer, as it wasn't connected to the region at that time. - // TODO: Feel free to replace this by a better solution if you find one. - - // get the agent. This should work every time, as we just got a packet from it - //ScenePresence agent = GetRootPresenceFromAgentID(agentID); - // KLUDGE 2: As this is sent quite early, the avatar isn't here as root agent yet. So, we have to cheat a bit - ScenePresence agent = GetAnyPresenceFromAgentID(agentID); - - // just to be paranoid... - if (agent == null) - { - m_log.ErrorFormat("[FRIEND]: Got a packet from agent {0} who can't be found anymore!?", agentID); - return; - } - - List fl; - lock (m_friendLists) - { - fl = (List)m_friendLists.Get(agent.ControllingClient.AgentId, - m_initialScene.GetFriendList); - } - - // tell everyone that we are online - SendPresenceState(agent.ControllingClient, fl, true); - } - - private void OnLogout(IClientAPI remoteClient) - { - List fl; - lock (m_friendLists) - { - fl = (List)m_friendLists.Get(remoteClient.AgentId, - m_initialScene.GetFriendList); - } - - // tell everyone that we are offline - SendPresenceState(remoteClient, fl, false); - } - } - - #endregion -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs deleted file mode 100644 index 969c1d8..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Gestures/GesturesModule.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using System.Reflection; - -namespace OpenSim.Region.Environment.Modules.Avatar.Gestures -{ - public class GesturesModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - - m_scene.EventManager.OnNewClient += OnNewClient; - } - - public void PostInitialise() {} - public void Close() {} - public string Name { get { return "Gestures Module"; } } - public bool IsSharedModule { get { return false; } } - - private void OnNewClient(IClientAPI client) - { - client.OnActivateGesture += ActivateGesture; - client.OnDeactivateGesture += DeactivateGesture; - } - - public virtual void ActivateGesture(IClientAPI client, UUID assetId, UUID gestureId) - { - CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(client.AgentId); - - if (userInfo != null) - { - InventoryItemBase item = userInfo.RootFolder.FindItem(gestureId); - if (item != null) - { - item.Flags = 1; - userInfo.UpdateItem(item); - } - else - m_log.ErrorFormat( - "[GESTURES]: Unable to find gesture to activate {0} for {1}", gestureId, client.Name); - } - else - m_log.ErrorFormat("[GESTURES]: Unable to find user {0}", client.Name); - } - - public virtual void DeactivateGesture(IClientAPI client, UUID gestureId) - { - CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(client.AgentId); - - if (userInfo != null) - { - InventoryItemBase item = userInfo.RootFolder.FindItem(gestureId); - if (item != null) - { - item.Flags = 0; - userInfo.UpdateItem(item); - } - else - m_log.ErrorFormat( - "[GESTURES]: Unable to find gesture to deactivate {0} for {1}", gestureId, client.Name); - } - else - m_log.ErrorFormat("[GESTURES]: Unable to find user {0}", client.Name); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs deleted file mode 100644 index e654912..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Groups -{ - public class GroupsModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Dictionary m_GroupMap = - new Dictionary(); - - private Dictionary m_ClientMap = - new Dictionary(); - - private UUID opensimulatorGroupID = - new UUID("00000000-68f9-1111-024e-222222111123"); - - private List m_SceneList = new List(); - - private static GroupMembershipData osGroup = - new GroupMembershipData(); - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - IConfig groupsConfig = config.Configs["Groups"]; - - if (groupsConfig == null) - { - m_log.Info("[GROUPS]: No configuration found. Using defaults"); - } - else - { - if (!groupsConfig.GetBoolean("Enabled", false)) - { - m_log.Info("[GROUPS]: Groups disabled in configuration"); - return; - } - - if (groupsConfig.GetString("Module", "Default") != "Default") - return; - } - - lock (m_SceneList) - { - if (!m_SceneList.Contains(scene)) - { - if (m_SceneList.Count == 0) - { - osGroup.GroupID = opensimulatorGroupID; - osGroup.GroupName = "OpenSimulator Testing"; - osGroup.GroupPowers = - (uint)(GroupPowers.AllowLandmark | - GroupPowers.AllowSetHome); - m_GroupMap[opensimulatorGroupID] = osGroup; - } - m_SceneList.Add(scene); - } - } - - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnClientClosed += OnClientClosed; - scene.EventManager.OnIncomingInstantMessage += - OnGridInstantMessage; - } - - public void PostInitialise() - { - } - - public void Close() - { -// m_log.Debug("[GROUPS]: Shutting down group module."); - - lock (m_ClientMap) - { - m_ClientMap.Clear(); - } - - lock (m_GroupMap) - { - m_GroupMap.Clear(); - } - } - - public string Name - { - get { return "GroupsModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void OnNewClient(IClientAPI client) - { - // Subscribe to instant messages - client.OnInstantMessage += OnInstantMessage; - client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; - client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; - lock (m_ClientMap) - { - if (!m_ClientMap.ContainsKey(client.AgentId)) - { - m_ClientMap.Add(client.AgentId, client); - } - } - - GroupMembershipData[] updateGroups = new GroupMembershipData[1]; - updateGroups[0] = osGroup; - - client.SendGroupMembership(updateGroups); - } - - private void OnAgentDataUpdateRequest(IClientAPI remoteClient, - UUID AgentID, UUID SessionID) - { - UUID ActiveGroupID; - string ActiveGroupName; - ulong ActiveGroupPowers; - - string firstname = remoteClient.FirstName; - string lastname = remoteClient.LastName; - - string ActiveGroupTitle = "I IZ N0T"; - - ActiveGroupID = osGroup.GroupID; - ActiveGroupName = osGroup.GroupName; - ActiveGroupPowers = osGroup.GroupPowers; - - remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, - lastname, ActiveGroupPowers, ActiveGroupName, - ActiveGroupTitle); - } - - private void OnInstantMessage(IClientAPI client, GridInstantMessage im) - { - } - - private void OnGridInstantMessage(GridInstantMessage msg) - { - // Trigger the above event handler - OnInstantMessage(null, msg); - } - - private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) - { - string groupnamereply = "Unknown"; - UUID groupUUID = UUID.Zero; - - lock (m_GroupMap) - { - if (m_GroupMap.ContainsKey(id)) - { - GroupMembershipData grp = m_GroupMap[id]; - groupnamereply = grp.GroupName; - groupUUID = grp.GroupID; - } - } - remote_client.SendGroupNameReply(groupUUID, groupnamereply); - } - - private void OnClientClosed(UUID agentID) - { - lock (m_ClientMap) - { - if (m_ClientMap.ContainsKey(agentID)) - { -// IClientAPI cli = m_ClientMap[agentID]; -// if (cli != null) -// { -// //m_log.Info("[GROUPS]: Removing all reference to groups for " + cli.Name); -// } -// else -// { -// //m_log.Info("[GROUPS]: Removing all reference to groups for " + agentID.ToString()); -// } - m_ClientMap.Remove(agentID); - } - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs deleted file mode 100644 index 3a1b282..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Net; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Client; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage -{ - public class InstantMessageModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Is this module enabled? - /// - private bool m_enabled = false; - - private readonly List m_scenes = new List(); - - #region IRegionModule Members - - private IMessageTransferModule m_TransferModule = null; - - public void Initialise(Scene scene, IConfigSource config) - { - if (config.Configs["Messaging"] != null) - { - if (config.Configs["Messaging"].GetString( - "InstantMessageModule", "InstantMessageModule") != - "InstantMessageModule") - return; - } - - m_enabled = true; - - lock (m_scenes) - { - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - scene.EventManager.OnClientConnect += OnClientConnect; - scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - } - } - } - - void OnClientConnect(IClientCore client) - { - IClientIM clientIM; - if (client.TryGet(out clientIM)) - { - clientIM.OnInstantMessage += OnInstantMessage; - } - } - - public void PostInitialise() - { - if (!m_enabled) - return; - - m_TransferModule = - m_scenes[0].RequestModuleInterface(); - - if (m_TransferModule == null) - m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+ - "IM will not work!"); - } - - public void Close() - { - } - - public string Name - { - get { return "InstantMessageModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - public void OnInstantMessage(IClientAPI client, GridInstantMessage im) - { - byte dialog = im.dialog; - - if ( dialog != (byte)InstantMessageDialog.MessageFromAgent - && dialog != (byte)InstantMessageDialog.StartTyping - && dialog != (byte)InstantMessageDialog.StopTyping) - { - return; - } - - if (m_TransferModule != null) - { - m_TransferModule.SendInstantMessage(im, - delegate(bool success) - { - if (dialog == (uint)InstantMessageDialog.StartTyping || - dialog == (uint)InstantMessageDialog.StopTyping) - { - return; - } - - if ((client != null) && !success) - { - client.SendInstantMessage(new UUID(im.toAgentID), - "Unable to send instant message. "+ - "User is not logged in.", - new UUID(im.fromAgentID), "System", - (byte)InstantMessageDialog.BusyAutoResponse, - (uint)Util.UnixTimeSinceEpoch()); - } - } - ); - } - } - - /// - /// - /// - /// - private void OnGridInstantMessage(GridInstantMessage msg) - { - // Just call the Text IM handler above - // This event won't be raised unless we have that agent, - // so we can depend on the above not trying to send - // via grid again - // - OnInstantMessage(null, msg); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs deleted file mode 100644 index 347c305..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Net; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Client; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage -{ - public class MessageTransferModule : IRegionModule, IMessageTransferModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // private bool m_Enabled = false; - private bool m_Gridmode = false; - private List m_Scenes = new List(); - private Dictionary m_UserRegionMap = new Dictionary(); - - public void Initialise(Scene scene, IConfigSource config) - { - IConfig cnf = config.Configs["Messaging"]; - if (cnf != null && cnf.GetString( - "MessageTransferModule", "MessageTransferModule") != - "MessageTransferModule") - return; - - cnf = config.Configs["Startup"]; - if (cnf != null) - m_Gridmode = cnf.GetBoolean("gridmode", false); - - // m_Enabled = true; - - lock (m_Scenes) - { - if (m_Scenes.Count == 0) - { - scene.CommsManager.HttpServer.AddXmlRPCHandler( - "grid_instant_message", processXMLRPCGridInstantMessage); - } - - scene.RegisterModuleInterface(this); - m_Scenes.Add(scene); - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "MessageTransferModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) - { - UUID toAgentID = new UUID(im.toAgentID); - - m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); - - // Try root avatar only first - foreach (Scene scene in m_Scenes) - { - if (scene.Entities.ContainsKey(toAgentID) && - scene.Entities[toAgentID] is ScenePresence) - { - m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); - // Local message - ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; - if (!user.IsChildAgent) - { - m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); - user.ControllingClient.SendInstantMessage( - new UUID(im.fromAgentID), - im.message, - new UUID(im.toAgentID), - im.fromAgentName, - im.dialog, - im.timestamp, - new UUID(im.imSessionID), - im.fromGroup, - im.binaryBucket); - // Message sent - result(true); - return; - } - } - } - - // try child avatar second - foreach (Scene scene in m_Scenes) - { -// m_log.DebugFormat( -// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); - - if (scene.Entities.ContainsKey(toAgentID) && - scene.Entities[toAgentID] is ScenePresence) - { - // Local message - ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; - - m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); - user.ControllingClient.SendInstantMessage( - new UUID(im.fromAgentID), - im.message, - new UUID(im.toAgentID), - im.fromAgentName, - im.dialog, - im.timestamp, - new UUID(im.imSessionID), - im.fromGroup, - im.binaryBucket); - // Message sent - result(true); - return; - } - } - - if (m_Gridmode) - { - //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid"); - // Still here, try send via Grid - SendGridInstantMessageViaXMLRPC(im, result); - return; - } - - //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); - result(false); - return; - } - - /// - /// Process a XMLRPC Grid Instant Message - /// - /// XMLRPC parameters - /// - /// Nothing much - protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request) - { - bool successful = false; - - // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that - // happen here and aren't caught and log them. - try - { - // various rational defaults - UUID fromAgentID = UUID.Zero; - UUID toAgentID = UUID.Zero; - UUID imSessionID = UUID.Zero; - uint timestamp = 0; - string fromAgentName = ""; - string message = ""; - byte dialog = (byte)0; - bool fromGroup = false; - byte offline = (byte)0; - uint ParentEstateID=0; - Vector3 Position = Vector3.Zero; - UUID RegionID = UUID.Zero ; - byte[] binaryBucket = new byte[0]; - - float pos_x = 0; - float pos_y = 0; - float pos_z = 0; - //m_log.Info("Processing IM"); - - - Hashtable requestData = (Hashtable)request.Params[0]; - // Check if it's got all the data - if (requestData.ContainsKey("from_agent_id") - && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id") - && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name") - && requestData.ContainsKey("message") && requestData.ContainsKey("dialog") - && requestData.ContainsKey("from_group") - && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id") - && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y") - && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") - && requestData.ContainsKey("binary_bucket")) - { - // Do the easy way of validating the UUIDs - UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); - UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); - UUID.TryParse((string)requestData["im_session_id"], out imSessionID); - UUID.TryParse((string)requestData["region_id"], out RegionID); - - try - { - timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - - fromAgentName = (string)requestData["from_agent_name"]; - message = (string)requestData["message"]; - - // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them. - string requestData1 = (string)requestData["dialog"]; - if (string.IsNullOrEmpty(requestData1)) - { - dialog = 0; - } - else - { - byte[] dialogdata = Convert.FromBase64String(requestData1); - dialog = dialogdata[0]; - } - - if ((string)requestData["from_group"] == "TRUE") - fromGroup = true; - - string requestData2 = (string)requestData["offline"]; - if (String.IsNullOrEmpty(requestData2)) - { - offline = 0; - } - else - { - byte[] offlinedata = Convert.FromBase64String(requestData2); - offline = offlinedata[0]; - } - - try - { - ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - - try - { - pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - try - { - pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - try - { - pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - - Position = new Vector3(pos_x, pos_y, pos_z); - - string requestData3 = (string)requestData["binary_bucket"]; - if (string.IsNullOrEmpty(requestData3)) - { - binaryBucket = new byte[0]; - } - else - { - binaryBucket = Convert.FromBase64String(requestData3); - } - - // Create a New GridInstantMessageObject the the data - GridInstantMessage gim = new GridInstantMessage(); - gim.fromAgentID = fromAgentID.Guid; - gim.fromAgentName = fromAgentName; - gim.fromGroup = fromGroup; - gim.imSessionID = imSessionID.Guid; - gim.RegionID = RegionID.Guid; - gim.timestamp = timestamp; - gim.toAgentID = toAgentID.Guid; - gim.message = message; - gim.dialog = dialog; - gim.offline = offline; - gim.ParentEstateID = ParentEstateID; - gim.Position = Position; - gim.binaryBucket = binaryBucket; - - - // Trigger the Instant message in the scene. - foreach (Scene scene in m_Scenes) - { - if (scene.Entities.ContainsKey(toAgentID) && - scene.Entities[toAgentID] is ScenePresence) - { - ScenePresence user = - (ScenePresence)scene.Entities[toAgentID]; - - if (!user.IsChildAgent) - { - scene.EventManager.TriggerIncomingInstantMessage(gim); - successful = true; - } - } - } - if (!successful) - { - // If the message can't be delivered to an agent, it - // is likely to be a group IM. On a group IM, the - // imSessionID = toAgentID = group id. Raise the - // unhandled IM event to give the groups module - // a chance to pick it up. We raise that in a random - // scene, since the groups module is shared. - // - m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim); - } - } - } - catch (Exception e) - { - m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e); - successful = false; - } - - //Send response back to region calling if it was successful - // calling region uses this to know when to look up a user's location again. - XmlRpcResponse resp = new XmlRpcResponse(); - Hashtable respdata = new Hashtable(); - if (successful) - respdata["success"] = "TRUE"; - else - respdata["success"] = "FALSE"; - resp.Value = respdata; - - return resp; - } - - /// - /// delegate for sending a grid instant message asynchronously - /// - public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle); - - private void GridInstantMessageCompleted(IAsyncResult iar) - { - GridInstantMessageDelegate icon = - (GridInstantMessageDelegate)iar.AsyncState; - icon.EndInvoke(iar); - } - - - protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) - { - GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; - - d.BeginInvoke(im, result, 0, GridInstantMessageCompleted, d); - } - - /// - /// Recursive SendGridInstantMessage over XMLRPC method. - /// This is called from within a dedicated thread. - /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from - /// itself, prevRegionHandle will be the last region handle that we tried to send. - /// If the handles are the same, we look up the user's location using the grid. - /// If the handles are still the same, we end. The send failed. - /// - /// - /// Pass in 0 the first time this method is called. It will be called recursively with the last - /// regionhandle tried - /// - protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle) - { - UUID toAgentID = new UUID(im.toAgentID); - - UserAgentData upd = null; - - bool lookupAgent = false; - - lock (m_UserRegionMap) - { - if (m_UserRegionMap.ContainsKey(toAgentID)) - { - upd = new UserAgentData(); - upd.AgentOnline = true; - upd.Handle = m_UserRegionMap[toAgentID]; - - // We need to compare the current regionhandle with the previous region handle - // or the recursive loop will never end because it will never try to lookup the agent again - if (prevRegionHandle == upd.Handle) - { - lookupAgent = true; - } - } - else - { - lookupAgent = true; - } - } - - - // Are we needing to look-up an agent? - if (lookupAgent) - { - // Non-cached user agent lookup. - upd = m_Scenes[0].CommsManager.UserService.GetAgentByUUID(toAgentID); - - if (upd != null) - { - // check if we've tried this before.. - // This is one way to end the recursive loop - // - if (upd.Handle == prevRegionHandle) - { - m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - result(false); - return; - } - } - else - { - m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - result(false); - return; - } - } - - if (upd != null) - { - if (upd.AgentOnline) - { - RegionInfo reginfo = m_Scenes[0].SceneGridService.RequestNeighbouringRegionInfo(upd.Handle); - if (reginfo != null) - { - Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); - // Not actually used anymore, left in for compatibility - // Remove at next interface change - // - msgdata["region_handle"] = 0; - bool imresult = doIMSending(reginfo, msgdata); - if (imresult) - { - // IM delivery successful, so store the Agent's location in our local cache. - lock (m_UserRegionMap) - { - if (m_UserRegionMap.ContainsKey(toAgentID)) - { - m_UserRegionMap[toAgentID] = upd.Handle; - } - else - { - m_UserRegionMap.Add(toAgentID, upd.Handle); - } - } - result(true); - } - else - { - // try again, but lookup user this time. - // Warning, this must call the Async version - // of this method or we'll be making thousands of threads - // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync - // The version that spawns the thread is SendGridInstantMessageViaXMLRPC - - // This is recursive!!!!! - SendGridInstantMessageViaXMLRPCAsync(im, result, - upd.Handle); - } - - } - else - { - m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.Handle); - result(false); - } - } - else - { - result(false); - } - } - else - { - m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find user {0}", toAgentID); - result(false); - } - - } - - /// - /// This actually does the XMLRPC Request - /// - /// RegionInfo we pull the data out of to send the request to - /// The Instant Message data Hashtable - /// Bool if the message was successfully delivered at the other side. - private bool doIMSending(RegionInfo reginfo, Hashtable xmlrpcdata) - { - - ArrayList SendParams = new ArrayList(); - SendParams.Add(xmlrpcdata); - XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); - try - { - - XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); - - Hashtable responseData = (Hashtable)GridResp.Value; - - if (responseData.ContainsKey("success")) - { - if ((string)responseData["success"] == "TRUE") - { - return true; - } - else - { - return false; - } - } - else - { - return false; - } - } - catch (WebException e) - { - m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})", - reginfo.ExternalHostName, reginfo.HttpPort, e.Message); - } - - return false; - } - - /// - /// Get ulong region handle for region by it's Region UUID. - /// We use region handles over grid comms because there's all sorts of free and cool caching. - /// - /// UUID of region to get the region handle for - /// -// private ulong getLocalRegionHandleFromUUID(UUID regionID) -// { -// ulong returnhandle = 0; -// -// lock (m_Scenes) -// { -// foreach (Scene sn in m_Scenes) -// { -// if (sn.RegionInfo.RegionID == regionID) -// { -// returnhandle = sn.RegionInfo.RegionHandle; -// break; -// } -// } -// } -// return returnhandle; -// } - - /// - /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC - /// - /// The GridInstantMessage object - /// Hashtable containing the XMLRPC request - private Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg) - { - Hashtable gim = new Hashtable(); - gim["from_agent_id"] = msg.fromAgentID.ToString(); - // Kept for compatibility - gim["from_agent_session"] = UUID.Zero.ToString(); - gim["to_agent_id"] = msg.toAgentID.ToString(); - gim["im_session_id"] = msg.imSessionID.ToString(); - gim["timestamp"] = msg.timestamp.ToString(); - gim["from_agent_name"] = msg.fromAgentName; - gim["message"] = msg.message; - byte[] dialogdata = new byte[1];dialogdata[0] = msg.dialog; - gim["dialog"] = Convert.ToBase64String(dialogdata,Base64FormattingOptions.None); - - if (msg.fromGroup) - gim["from_group"] = "TRUE"; - else - gim["from_group"] = "FALSE"; - byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline; - gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None); - gim["parent_estate_id"] = msg.ParentEstateID.ToString(); - gim["position_x"] = msg.Position.X.ToString(); - gim["position_y"] = msg.Position.Y.ToString(); - gim["position_z"] = msg.Position.Z.ToString(); - gim["region_id"] = msg.RegionID.ToString(); - gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); - return gim; - } - - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs deleted file mode 100644 index c84d3d5..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Net; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Client; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage -{ - public class PresenceModule : IRegionModule, IPresenceModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private bool m_Enabled = false; - private bool m_Gridmode = false; - - // some default scene for doing things that aren't connected to a specific scene. Avoids locking. - private Scene m_initialScene; - - private List m_Scenes = new List(); - - // we currently are only interested in root-agents. If the root isn't here, we don't know the region the - // user is in, so we have to ask the messaging server anyway. - private Dictionary m_RootAgents = - new Dictionary(); - - public event PresenceChange OnPresenceChange; - public event BulkPresenceData OnBulkPresenceData; - - public void Initialise(Scene scene, IConfigSource config) - { - lock (m_Scenes) - { - // This is a shared module; Initialise will be called for every region on this server. - // Only check config once for the first region. - if (m_Scenes.Count == 0) - { - IConfig cnf = config.Configs["Messaging"]; - if (cnf != null && cnf.GetString( - "PresenceModule", "PresenceModule") != - "PresenceModule") - return; - - cnf = config.Configs["Startup"]; - if (cnf != null) - m_Gridmode = cnf.GetBoolean("gridmode", false); - - m_Enabled = true; - - m_initialScene = scene; - } - - if (m_Gridmode) - NotifyMessageServerOfStartup(scene); - - m_Scenes.Add(scene); - } - - scene.RegisterModuleInterface(this); - - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; - scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; - } - - public void PostInitialise() - { - } - - public void Close() - { - if (!m_Gridmode || !m_Enabled) - return; - - if (OnPresenceChange != null) - { - lock (m_RootAgents) - { - // on shutdown, users are kicked, too - foreach (KeyValuePair pair in m_RootAgents) - { - OnPresenceChange(new PresenceInfo(pair.Key, UUID.Zero)); - } - } - } - - lock (m_Scenes) - { - foreach (Scene scene in m_Scenes) - NotifyMessageServerOfShutdown(scene); - } - } - - public string Name - { - get { return "PresenceModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public void RequestBulkPresenceData(UUID[] users) - { - if (OnBulkPresenceData != null) - { - PresenceInfo[] result = new PresenceInfo[users.Length]; - if (m_Gridmode) - { - // first check the local information - List uuids = new List(); // the uuids to check remotely - List indices = new List(); // just for performance. - lock (m_RootAgents) - { - for (int i = 0; i < uuids.Count; ++i) - { - Scene scene; - if (m_RootAgents.TryGetValue(users[i], out scene)) - { - result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID); - } - else - { - uuids.Add(users[i]); - indices.Add(i); - } - } - } - - // now we have filtered out all the local root agents. The rest we have to request info about - Dictionary infos = m_initialScene.GetFriendRegionInfos(uuids); - for (int i = 0; i < uuids.Count; ++i) - { - FriendRegionInfo info; - if (infos.TryGetValue(uuids[i], out info) && info.isOnline) - { - UUID regionID = info.regionID; - if (regionID == UUID.Zero) - { - // TODO this is the old messaging-server protocol; only the regionHandle is available. - // Fetch region-info to get the id - RegionInfo regionInfo = m_initialScene.RequestNeighbouringRegionInfo(info.regionHandle); - regionID = regionInfo.RegionID; - } - result[indices[i]] = new PresenceInfo(uuids[i], regionID); - } - else result[indices[i]] = new PresenceInfo(uuids[i], UUID.Zero); - } - } - else - { - // in standalone mode, we have all the info locally available. - lock (m_RootAgents) - { - for (int i = 0; i < users.Length; ++i) - { - Scene scene; - if (m_RootAgents.TryGetValue(users[i], out scene)) - { - result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID); - } - else - { - result[i] = new PresenceInfo(users[i], UUID.Zero); - } - } - } - } - - // tell everyone - OnBulkPresenceData(result); - } - } - - // new client doesn't mean necessarily that user logged in, it just means it entered one of the - // the regions on this server - public void OnNewClient(IClientAPI client) - { - client.OnConnectionClosed += OnConnectionClosed; - client.OnLogout += OnLogout; - - // KLUDGE: See handler for details. - client.OnEconomyDataRequest += OnEconomyDataRequest; - } - - // connection closed just means *one* client connection has been closed. It doesn't mean that the - // user has logged off; it might have just TPed away. - public void OnConnectionClosed(IClientAPI client) - { - // TODO: Have to think what we have to do here... - // Should we just remove the root from the list (if scene matches)? - if (!(client.Scene is Scene)) - return; - Scene scene = (Scene)client.Scene; - - lock (m_RootAgents) - { - Scene rootScene; - if (!(m_RootAgents.TryGetValue(client.AgentId, out rootScene)) || scene != rootScene) - return; - - m_RootAgents.Remove(client.AgentId); - } - - // Should it have logged off, we'll do the logout part in OnLogout, even if no root is stored - // anymore. It logged off, after all... - } - - // Triggered when the user logs off. - public void OnLogout(IClientAPI client) - { - if (!(client.Scene is Scene)) - return; - Scene scene = (Scene)client.Scene; - - // On logout, we really remove the client from rootAgents, even if the scene doesn't match - lock (m_RootAgents) - { - if (m_RootAgents.ContainsKey(client.AgentId)) m_RootAgents.Remove(client.AgentId); - } - - // now inform the messaging server and anyone who is interested - NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); - if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(client.AgentId, UUID.Zero)); - } - - public void OnSetRootAgentScene(UUID agentID, Scene scene) - { - // OnSetRootAgentScene can be called from several threads at once (with different agentID). - // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without - // correct locking). - lock (m_RootAgents) - { - Scene rootScene; - if (m_RootAgents.TryGetValue(agentID, out rootScene) && scene == rootScene) - { - return; - } - m_RootAgents[agentID] = scene; - } - // inform messaging server that agent changed the region - NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); - } - - private void OnEconomyDataRequest(UUID agentID) - { - // KLUDGE: This is the only way I found to get a message (only) after login was completed and the - // client is connected enough to receive UDP packets. - // This packet seems to be sent only once, just after connection was established to the first - // region after login. - // We use it here to trigger a presence update; the old update-on-login was never be heard by - // the freshly logged in viewer, as it wasn't connected to the region at that time. - // TODO: Feel free to replace this by a better solution if you find one. - - // get the agent. This should work every time, as we just got a packet from it - ScenePresence agent = null; - lock (m_Scenes) - { - foreach (Scene scene in m_Scenes) - { - agent = scene.GetScenePresence(agentID); - if (agent != null) break; - } - } - - // just to be paranoid... - if (agent == null) - { - m_log.ErrorFormat("[PRESENCE]: Got a packet from agent {0} who can't be found anymore!?", agentID); - return; - } - - // we are a bit premature here, but the next packet will switch this child agent to root. - if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(agentID, agent.Scene.RegionInfo.RegionID)); - } - - public void OnMakeChildAgent(ScenePresence agent) - { - // OnMakeChildAgent can be called from several threads at once (with different agent). - // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without - // correct locking). - lock (m_RootAgents) - { - Scene rootScene; - if (m_RootAgents.TryGetValue(agent.UUID, out rootScene) && agent.Scene == rootScene) - { - m_RootAgents.Remove(agent.UUID); - } - } - // don't notify the messaging-server; either this agent just had been downgraded and another one will be upgraded - // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment, - // which will update the messaging-server, too. - } - - private void NotifyMessageServerOfStartup(Scene scene) - { - Hashtable xmlrpcdata = new Hashtable(); - xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString(); - ArrayList SendParams = new ArrayList(); - SendParams.Add(xmlrpcdata); - try - { - XmlRpcRequest UpRequest = new XmlRpcRequest("region_startup", SendParams); - XmlRpcResponse resp = UpRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000); - - Hashtable responseData = (Hashtable)resp.Value; - if (responseData == null || (!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName); - } - } - catch (System.Net.WebException) - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName); - } - } - - private void NotifyMessageServerOfShutdown(Scene scene) - { - Hashtable xmlrpcdata = new Hashtable(); - xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString(); - ArrayList SendParams = new ArrayList(); - SendParams.Add(xmlrpcdata); - try - { - XmlRpcRequest DownRequest = new XmlRpcRequest("region_shutdown", SendParams); - XmlRpcResponse resp = DownRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000); - - Hashtable responseData = (Hashtable)resp.Value; - if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName); - } - } - catch (System.Net.WebException) - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName); - } - } - - private void NotifyMessageServerOfAgentLocation(UUID agentID, UUID region, ulong regionHandle) - { - Hashtable xmlrpcdata = new Hashtable(); - xmlrpcdata["AgentID"] = agentID.ToString(); - xmlrpcdata["RegionUUID"] = region.ToString(); - xmlrpcdata["RegionHandle"] = regionHandle.ToString(); - ArrayList SendParams = new ArrayList(); - SendParams.Add(xmlrpcdata); - try - { - XmlRpcRequest LocationRequest = new XmlRpcRequest("agent_location", SendParams); - XmlRpcResponse resp = LocationRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000); - - Hashtable responseData = (Hashtable)resp.Value; - if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString()); - } - } - catch (System.Net.WebException) - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString()); - } - } - - private void NotifyMessageServerOfAgentLeaving(UUID agentID, UUID region, ulong regionHandle) - { - Hashtable xmlrpcdata = new Hashtable(); - xmlrpcdata["AgentID"] = agentID.ToString(); - xmlrpcdata["RegionUUID"] = region.ToString(); - xmlrpcdata["RegionHandle"] = regionHandle.ToString(); - ArrayList SendParams = new ArrayList(); - SendParams.Add(xmlrpcdata); - try - { - XmlRpcRequest LeavingRequest = new XmlRpcRequest("agent_leaving", SendParams); - XmlRpcResponse resp = LeavingRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000); - - Hashtable responseData = (Hashtable)resp.Value; - if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString()); - } - } - catch (System.Net.WebException) - { - m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString()); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs deleted file mode 100644 index 3a58202..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Reflection; -using System.Xml; -using OpenMetaverse; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Archiver; -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Cache; -using log4net; -using OpenSim.Region.Environment.Modules.World.Serialiser; - - -namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Archiver -{ - public class InventoryArchiveReadRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene scene; - protected TarArchiveReader archive; - private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); - - CommunicationsManager commsManager; - - public InventoryArchiveReadRequest(Scene currentScene, CommunicationsManager commsManager) - { - //List serialisedObjects = new List(); - scene = currentScene; - this.commsManager = commsManager; - } - - protected InventoryItemBase loadInvItem(string path, string contents) - { - InventoryItemBase item = new InventoryItemBase(); - StringReader sr = new StringReader(contents); - XmlTextReader reader = new XmlTextReader(sr); - - if (contents.Equals("")) return null; - - reader.ReadStartElement("InventoryObject"); - reader.ReadStartElement("Name"); - item.Name = reader.ReadString(); - reader.ReadEndElement(); - reader.ReadStartElement("ID"); - item.ID = UUID.Parse(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("InvType"); - item.InvType = System.Convert.ToInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("CreatorUUID"); - item.Creator = UUID.Parse(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("CreationDate"); - item.CreationDate = System.Convert.ToInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("Owner"); - item.Owner = UUID.Parse(reader.ReadString()); - reader.ReadEndElement(); - //No description would kill it - if (reader.IsEmptyElement) - { - reader.ReadStartElement("Description"); - } - else - { - reader.ReadStartElement("Description"); - item.Description = reader.ReadString(); - reader.ReadEndElement(); - } - reader.ReadStartElement("AssetType"); - item.AssetType = System.Convert.ToInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("AssetID"); - item.AssetID = UUID.Parse(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("SaleType"); - item.SaleType = System.Convert.ToByte(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("SalePrice"); - item.SalePrice = System.Convert.ToInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("BasePermissions"); - item.BasePermissions = System.Convert.ToUInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("CurrentPermissions"); - item.CurrentPermissions = System.Convert.ToUInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("EveryOnePermssions"); - item.EveryOnePermissions = System.Convert.ToUInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("NextPermissions"); - item.NextPermissions = System.Convert.ToUInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("Flags"); - item.Flags = System.Convert.ToUInt32(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("GroupID"); - item.GroupID = UUID.Parse(reader.ReadString()); - reader.ReadEndElement(); - reader.ReadStartElement("GroupOwned"); - item.GroupOwned = System.Convert.ToBoolean(reader.ReadString()); - reader.ReadEndElement(); - //reader.ReadStartElement("ParentFolderID"); - //item.Folder = UUID.Parse(reader.ReadString()); - //reader.ReadEndElement(); - //reader.ReadEndElement(); - - return item; - } - - public void execute(string firstName, string lastName, string invPath, string loadPath) - { - string filePath = "ERROR"; - int successfulAssetRestores = 0; - int failedAssetRestores = 0; - int successfulItemRestores = 0; - - UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName); - if (null == userProfile) - { - m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName); - return; - } - - CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID); - if (null == userInfo) - { - m_log.ErrorFormat( - "[CONSOLE]: Failed to find user info for {0} {1} {2}", - firstName, lastName, userProfile.ID); - - return; - } - - if (!userInfo.HasReceivedInventory) - { - m_log.ErrorFormat( - "[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}", - firstName, lastName, userProfile.ID); - - return; - } - - InventoryFolderImpl inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath); - - if (null == inventoryFolder) - { - // TODO: Later on, automatically create this folder if it does not exist - m_log.ErrorFormat("[ARCHIVER]: Inventory path {0} does not exist", invPath); - - return; - } - - archive - = new TarArchiveReader(new GZipStream( - new FileStream(loadPath, FileMode.Open), CompressionMode.Decompress)); - - byte[] data; - TarArchiveReader.TarEntryType entryType; - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) - { - if (entryType == TarArchiveReader.TarEntryType.TYPE_DIRECTORY) { - m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", filePath); - } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - if (LoadAsset(filePath, data)) - successfulAssetRestores++; - else - failedAssetRestores++; - } - else - { - InventoryItemBase item = loadInvItem(filePath, m_asciiEncoding.GetString(data)); - - if (item != null) - { - item.Creator = userProfile.ID; - item.Owner = userProfile.ID; - - // Reset folder ID to the one in which we want to load it - // TODO: Properly restore entire folder structure. At the moment all items are dumped in this - // single folder no matter where in the saved folder structure they are. - item.Folder = inventoryFolder.ID; - - userInfo.AddItem(item); - successfulItemRestores++; - } - } - } - - archive.Close(); - - m_log.DebugFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); - m_log.InfoFormat("[ARCHIVER]: Restored {0} items", successfulItemRestores); - } - - /// - /// Load an asset - /// - /// - /// - /// true if asset was successfully loaded, false otherwise - private bool LoadAsset(string assetPath, byte[] data) - { - //IRegionSerialiser serialiser = scene.RequestModuleInterface(); - // Right now we're nastily obtaining the UUID from the filename - string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); - int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR); - - if (i == -1) - { - m_log.ErrorFormat( - "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping", - assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR); - - return false; - } - - string extension = filename.Substring(i); - string uuid = filename.Remove(filename.Length - extension.Length); - - if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) - { - sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; - - m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); - - AssetBase asset = new AssetBase(new UUID(uuid), "RandomName"); - - asset.Metadata.Type = assetType; - asset.Data = data; - - scene.AssetCache.AddAsset(asset); - - - return true; - } - else - { - m_log.ErrorFormat( - "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}", - assetPath, extension); - - return false; - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs deleted file mode 100644 index e23f2a8..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Reflection; -using System.Xml; -using OpenMetaverse; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Archiver; -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Cache; -using log4net; - - -namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Archiver -{ - public class InventoryArchiveWriteRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene scene; - protected TarArchiveWriter archive; - protected CommunicationsManager commsManager; - Dictionary assetUuids; - - /// - /// The path to which the inventory archive will be saved. - /// - private string m_savePath; - - public InventoryArchiveWriteRequest(Scene currentScene, CommunicationsManager commsManager) - { - scene = currentScene; - archive = new TarArchiveWriter(); - this.commsManager = commsManager; - assetUuids = new Dictionary(); - } - - protected void ReceivedAllAssets(IDictionary assetsFound, ICollection assetsNotFoundUuids) - { - AssetsArchiver assetsArchiver = new AssetsArchiver(assetsFound); - assetsArchiver.Archive(archive); - archive.WriteTar(new GZipStream(new FileStream(m_savePath, FileMode.Create), CompressionMode.Compress)); - } - - protected void saveInvItem(InventoryItemBase inventoryItem, string path) - { - string filename - = string.Format("{0}{1}_{2}.xml", - path, inventoryItem.Name, inventoryItem.ID); - StringWriter sw = new StringWriter(); - XmlTextWriter writer = new XmlTextWriter(sw); - writer.WriteStartElement("InventoryObject"); - writer.WriteStartElement("Name"); - writer.WriteString(inventoryItem.Name); - writer.WriteEndElement(); - writer.WriteStartElement("ID"); - writer.WriteString(inventoryItem.ID.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("InvType"); - writer.WriteString(inventoryItem.InvType.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("CreatorUUID"); - writer.WriteString(inventoryItem.Creator.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("CreationDate"); - writer.WriteString(inventoryItem.CreationDate.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("Owner"); - writer.WriteString(inventoryItem.Owner.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("Description"); - if (inventoryItem.Description.Length > 0) - writer.WriteString(inventoryItem.Description); - else writer.WriteString("No Description"); - writer.WriteEndElement(); - writer.WriteStartElement("AssetType"); - writer.WriteString(inventoryItem.AssetType.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("AssetID"); - writer.WriteString(inventoryItem.AssetID.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("SaleType"); - writer.WriteString(inventoryItem.SaleType.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("SalePrice"); - writer.WriteString(inventoryItem.SalePrice.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("BasePermissions"); - writer.WriteString(inventoryItem.BasePermissions.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("CurrentPermissions"); - writer.WriteString(inventoryItem.CurrentPermissions.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("EveryOnePermssions"); - writer.WriteString(inventoryItem.EveryOnePermissions.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("NextPermissions"); - writer.WriteString(inventoryItem.NextPermissions.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("Flags"); - writer.WriteString(inventoryItem.Flags.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("GroupID"); - writer.WriteString(inventoryItem.GroupID.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("GroupOwned"); - writer.WriteString(inventoryItem.GroupOwned.ToString()); - writer.WriteEndElement(); - writer.WriteStartElement("ParentFolderID"); - writer.WriteString(inventoryItem.Folder.ToString()); - writer.WriteEndElement(); - writer.WriteEndElement(); - - archive.AddFile(filename, sw.ToString()); - - assetUuids[inventoryItem.AssetID] = 1; - } - - protected void saveInvDir(InventoryFolderImpl inventoryFolder, string path) - { - List inventories = inventoryFolder.RequestListOfFolderImpls(); - List items = inventoryFolder.RequestListOfItems(); - string newPath = path + inventoryFolder.Name + InventoryFolderImpl.PATH_DELIMITER; - archive.AddDir(newPath); - foreach (InventoryFolderImpl folder in inventories) - { - saveInvDir(folder, newPath); - } - foreach (InventoryItemBase item in items) - { - saveInvItem(item, newPath); - } - } - - public void execute(string firstName, string lastName, string invPath, string savePath) - { - m_savePath = savePath; - - UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName); - if (null == userProfile) - { - m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName); - return; - } - - CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID); - if (null == userInfo) - { - m_log.ErrorFormat("[CONSOLE]: Failed to find user info for {0} {1} {2}", firstName, lastName, userProfile.ID); - return; - } - - InventoryFolderImpl inventoryFolder = null; - InventoryItemBase inventoryItem = null; - - if (userInfo.HasReceivedInventory) - { - // Eliminate double slashes and any leading / on the path. This might be better done within InventoryFolderImpl - // itself (possibly at a small loss in efficiency). - string[] components - = invPath.Split(new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); - invPath = String.Empty; - foreach (string c in components) - { - invPath += c + InventoryFolderImpl.PATH_DELIMITER; - } - - // Annoyingly Split actually returns the original string if the input string consists only of delimiters - // Therefore if we still start with a / after the split, then we need the root folder - if (invPath.Length == 0) - { - inventoryFolder = userInfo.RootFolder; - } - else - { - invPath = invPath.Remove(invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); - inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath); - } - - // The path may point to an item instead - if (inventoryFolder == null) - { - inventoryItem = userInfo.RootFolder.FindItemByPath(invPath); - } - } - else - { - m_log.ErrorFormat("[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}", firstName, lastName, userProfile.ID); - return; - } - - if (null == inventoryFolder) - { - if (null == inventoryItem) - { - m_log.ErrorFormat("[CONSOLE]: Could not find inventory entry at path {0}", invPath); - return; - } - else - { - m_log.InfoFormat("[CONSOLE]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, - invPath); - //get and export item info - saveInvItem(inventoryItem, invPath); - } - } - else - { - m_log.InfoFormat("[CONSOLE]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID, - invPath); - //recurse through all dirs getting dirs and files - saveInvDir(inventoryFolder, ""); - } - - new AssetsRequest(assetUuids.Keys, scene.AssetCache, ReceivedAllAssets).Execute(); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs deleted file mode 100644 index 62fb3a2..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework.Communications.Cache; - -namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer -{ - public class InventoryTransferModule : IInventoryTransferModule, IRegionModule - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - private List m_Scenelist = new List(); - private Dictionary m_AgentRegions = - new Dictionary(); - - private IMessageTransferModule m_TransferModule = null; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (config.Configs["Messaging"] != null) - { - // Allow disabling this module in config - // - if (config.Configs["Messaging"].GetString( - "InventoryTransferModule", "InventoryTransferModule") != - "InventoryTransferModule") - return; - } - - if (!m_Scenelist.Contains(scene)) - { - if (m_Scenelist.Count == 0) - { - m_TransferModule = scene.RequestModuleInterface(); - if (m_TransferModule == null) - m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only"); - } - - m_Scenelist.Add(scene); - - scene.RegisterModuleInterface(this); - - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnClientClosed += ClientLoggedOut; - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "InventoryModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void OnNewClient(IClientAPI client) - { - // Inventory giving is conducted via instant message - client.OnInstantMessage += OnInstantMessage; - } - - private Scene FindClientScene(UUID agentId) - { - lock (m_Scenelist) - { - foreach (Scene scene in m_Scenelist) - { - ScenePresence presence = scene.GetScenePresence(agentId); - if (presence != null) - { - if (!presence.IsChildAgent) - return scene; - } - } - } - return null; - } - - private void OnInstantMessage(IClientAPI client, GridInstantMessage im) - { - Scene scene = FindClientScene(client.AgentId); - - if (scene == null) // Something seriously wrong here. - return; - - if (im.dialog == (byte) InstantMessageDialog.InventoryOffered) - { - //m_log.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); - - ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); - UUID copyID; - - // First byte is the asset type - AssetType assetType = (AssetType)im.binaryBucket[0]; - - if (AssetType.Folder == assetType) - { - UUID folderID = new UUID(im.binaryBucket, 1); - - m_log.DebugFormat("[AGENT INVENTORY]: Inserting original folder {0} "+ - "into agent {1}'s inventory", - folderID, new UUID(im.toAgentID)); - - InventoryFolderImpl folderCopy - = scene.GiveInventoryFolder(new UUID(im.toAgentID), client.AgentId, folderID, UUID.Zero); - - if (folderCopy == null) - { - client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false); - return; - } - - // The outgoing binary bucket should contain only the byte which signals an asset folder is - // being copied and the following bytes for the copied folder's UUID - copyID = folderCopy.ID; - byte[] copyIDBytes = copyID.GetBytes(); - im.binaryBucket = new byte[1 + copyIDBytes.Length]; - im.binaryBucket[0] = (byte)AssetType.Folder; - Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length); - - if (user != null && !user.IsChildAgent) - { - user.ControllingClient.SendBulkUpdateInventory(folderCopy); - } - } - else - { - // First byte of the array is probably the item type - // Next 16 bytes are the UUID - - UUID itemID = new UUID(im.binaryBucket, 1); - - m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+ - "into agent {1}'s inventory", - itemID, new UUID(im.toAgentID)); - - InventoryItemBase itemCopy = scene.GiveInventoryItem( - new UUID(im.toAgentID), - client.AgentId, itemID); - - if (itemCopy == null) - { - client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); - return; - } - - copyID = itemCopy.ID; - Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16); - - if (user != null && !user.IsChildAgent) - { - user.ControllingClient.SendBulkUpdateInventory(itemCopy); - } - } - - // Send the IM to the recipient. The item is already - // in their inventory, so it will not be lost if - // they are offline. - // - if (user != null && !user.IsChildAgent) - { - // And notify. Transaction ID is the item ID. We get that - // same ID back on the reply so we know what to act on - // - user.ControllingClient.SendInstantMessage( - new UUID(im.fromAgentID), im.message, - new UUID(im.toAgentID), - im.fromAgentName, im.dialog, im.timestamp, - copyID, false, im.binaryBucket); - - return; - } - else - { - if (m_TransferModule != null) - m_TransferModule.SendInstantMessage(im, delegate(bool success) {} ); - } - } - else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) - { - ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); - - if (user != null) // Local - { - user.ControllingClient.SendInstantMessage( - new UUID(im.fromAgentID), im.message, - new UUID(im.toAgentID), - im.fromAgentName, im.dialog, im.timestamp, - UUID.Zero, false, im.binaryBucket); - } - else - { - if (m_TransferModule != null) - m_TransferModule.SendInstantMessage(im, delegate(bool success) {} ); - } - } - else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined) - { - // Here, the recipient is local and we can assume that the - // inventory is loaded. Courtesy of the above bulk update, - // It will have been pushed to the client, too - // - - CachedUserInfo userInfo = - scene.CommsManager.UserProfileCacheService. - GetUserDetails(client.AgentId); - - if (userInfo != null) - { - InventoryFolderImpl trashFolder = - userInfo.FindFolderForType((int)AssetType.TrashFolder); - - UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip - - InventoryItemBase item = userInfo.RootFolder.FindItem(inventoryEntityID); - InventoryFolderBase folder = null; - - if (item != null && trashFolder != null) - { - item.Folder = trashFolder.ID; - - userInfo.DeleteItem(inventoryEntityID); - - scene.AddInventoryItem(client, item); - } - else - { - folder = userInfo.RootFolder.FindFolder(inventoryEntityID); - - if (folder != null & trashFolder != null) - { - userInfo.MoveFolder(inventoryEntityID, trashFolder.ID); - } - } - - if ((null == item && null == folder) | null == trashFolder) - { - string reason = String.Empty; - - if (trashFolder == null) - reason += " Trash folder not found."; - if (item == null) - reason += " Item not found."; - if (folder == null) - reason += " Folder not found."; - - client.SendAgentAlertMessage("Unable to delete "+ - "received inventory" + reason, false); - } - } - - ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); - - if (user != null) // Local - { - user.ControllingClient.SendInstantMessage( - new UUID(im.fromAgentID), im.message, - new UUID(im.toAgentID), - im.fromAgentName, im.dialog, im.timestamp, - UUID.Zero, false, im.binaryBucket); - } - else - { - if (m_TransferModule != null) - m_TransferModule.SendInstantMessage(im, delegate(bool success) {} ); - } - } - } - - public void SetRootAgentScene(UUID agentID, Scene scene) - { - m_AgentRegions[agentID] = scene; - } - - public bool NeedSceneCacheClear(UUID agentID, Scene scene) - { - if (!m_AgentRegions.ContainsKey(agentID)) - { - // Since we can get here two ways, we need to scan - // the scenes here. This is somewhat more expensive - // but helps avoid a nasty bug - // - - foreach (Scene s in m_Scenelist) - { - ScenePresence presence; - - if (s.TryGetAvatar(agentID, out presence)) - { - // If the agent is in this scene, then we - // are being called twice in a single - // teleport. This is wasteful of cycles - // but harmless due to this 2nd level check - // - // If the agent is found in another scene - // then the list wasn't current - // - // If the agent is totally unknown, then what - // are we even doing here?? - // - if (s == scene) - { - //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); - return true; - } - else - { - //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); - return false; - } - } - } - //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); - return true; - } - - // The agent is left in current Scene, so we must be - // going to another instance - // - if (m_AgentRegions[agentID] == scene) - { - //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); - m_AgentRegions.Remove(agentID); - return true; - } - - // Another region has claimed the agent - // - //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); - return false; - } - - public void ClientLoggedOut(UUID agentID) - { - if (m_AgentRegions.ContainsKey(agentID)) - m_AgentRegions.Remove(agentID); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs deleted file mode 100644 index 79d5409..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Lure/LureModule.cs +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Net; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Client; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Lure -{ - public class LureModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private readonly List m_scenes = new List(); - - private IMessageTransferModule m_TransferModule = null; - - public void Initialise(Scene scene, IConfigSource config) - { - if (config.Configs["Messaging"] != null) - { - if (config.Configs["Messaging"].GetString( - "LureModule", "LureModule") != - "LureModule") - return; - } - - lock (m_scenes) - { - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnIncomingInstantMessage += - OnGridInstantMessage; - } - } - } - - void OnNewClient(IClientAPI client) - { - client.OnInstantMessage += OnInstantMessage; - client.OnStartLure += OnStartLure; - client.OnTeleportLureRequest += OnTeleportLureRequest; - } - - public void PostInitialise() - { - m_TransferModule = - m_scenes[0].RequestModuleInterface(); - - if (m_TransferModule == null) - m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+ - "lures will not work!"); - } - - public void Close() - { - } - - public string Name - { - get { return "LureModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public void OnInstantMessage(IClientAPI client, GridInstantMessage im) - { - } - - public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client) - { - if (!(client.Scene is Scene)) - return; - - Scene scene = (Scene)(client.Scene); - ScenePresence presence = scene.GetScenePresence(client.AgentId); - - UUID dest = Util.BuildFakeParcelID( - scene.RegionInfo.RegionHandle, - (uint)presence.AbsolutePosition.X, - (uint)presence.AbsolutePosition.Y, - (uint)presence.AbsolutePosition.Z); - - m_log.DebugFormat("TP invite with message {0}", message); - - GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, - client.FirstName+" "+client.LastName, targetid, - (byte)InstantMessageDialog.RequestTeleport, false, - message, dest, false, presence.AbsolutePosition, - new Byte[0]); - - if (m_TransferModule != null) - { - m_TransferModule.SendInstantMessage(m, - delegate(bool success) { }); - } - } - - public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client) - { - if (!(client.Scene is Scene)) - return; - - Scene scene = (Scene)(client.Scene); - - ulong handle = 0; - uint x = 128; - uint y = 128; - uint z = 70; - - Util.ParseFakeParcelID(lureID, out handle, out x, out y, out z); - - Vector3 position = new Vector3(); - position.X = (float)x; - position.Y = (float)y; - position.Z = (float)z; - - scene.RequestTeleportLocation(client, handle, position, - Vector3.Zero, teleportFlags); - } - - private void OnGridInstantMessage(GridInstantMessage msg) - { - // Forward remote teleport requests - // - if (msg.dialog != 22) - return; - - if (m_TransferModule != null) - { - m_TransferModule.SendInstantMessage(msg, - delegate(bool success) { }); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs deleted file mode 100644 index c853582..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/ObjectCaps/ObjectAdd.cs +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Caps = OpenSim.Framework.Communications.Capabilities.Caps; - -namespace OpenSim.Region.Environment.Modules.Avatar.ObjectCaps -{ - public class ObjectAdd : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Scene m_scene; - #region IRegionModule Members - - public void Initialise(Scene pScene, IConfigSource pSource) - { - m_scene = pScene; - m_scene.EventManager.OnRegisterCaps += RegisterCaps; - } - - public void PostInitialise() - { - - } - - public void RegisterCaps(UUID agentID, Caps caps) - { - UUID capuuid = UUID.Random(); - - m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/"); - - caps.RegisterHandler("ObjectAdd", - new RestHTTPHandler("POST", "/CAPS/OA/" + capuuid + "/", - delegate(Hashtable m_dhttpMethod) - { - return ProcessAdd(m_dhttpMethod, agentID, caps); - })); - } - - public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap) - { - Hashtable responsedata = new Hashtable(); - responsedata["int_response_code"] = 400; //501; //410; //404; - responsedata["content_type"] = "text/plain"; - responsedata["keepalive"] = false; - responsedata["str_response_string"] = "Request wasn't what was expected"; - ScenePresence avatar; - - if (!m_scene.TryGetAvatar(AgentId, out avatar)) - return responsedata; - - - OSD r = OSDParser.DeserializeLLSDXml((string)request["requestbody"]); - //UUID session_id = UUID.Zero; - bool bypass_raycast = false; - uint everyone_mask = 0; - uint group_mask = 0; - uint next_owner_mask = 0; - uint flags = 0; - UUID group_id = UUID.Zero; - int hollow = 0; - int material = 0; - int p_code = 0; - int path_begin = 0; - int path_curve = 0; - int path_end = 0; - int path_radius_offset = 0; - int path_revolutions = 0; - int path_scale_x = 0; - int path_scale_y = 0; - int path_shear_x = 0; - int path_shear_y = 0; - int path_skew = 0; - int path_taper_x = 0; - int path_taper_y = 0; - int path_twist = 0; - int path_twist_begin = 0; - int profile_begin = 0; - int profile_curve = 0; - int profile_end = 0; - Vector3 ray_end = Vector3.Zero; - bool ray_end_is_intersection = false; - Vector3 ray_start = Vector3.Zero; - UUID ray_target_id = UUID.Zero; - Quaternion rotation = Quaternion.Identity; - Vector3 scale = Vector3.Zero; - int state = 0; - - if (r.Type != OSDType.Map) // not a proper req - return responsedata; - - OSDMap rm = (OSDMap)r; - - if (rm.ContainsKey("ObjectData")) //v2 - { - if (rm["ObjectData"].Type != OSDType.Map) - { - responsedata["str_response_string"] = "Has ObjectData key, but data not in expected format"; - return responsedata; - } - - OSDMap ObjMap = (OSDMap) rm["ObjectData"]; - - bypass_raycast = ObjMap["BypassRaycast"].AsBoolean(); - everyone_mask = readuintval(ObjMap["EveryoneMask"]); - flags = readuintval(ObjMap["Flags"]); - group_mask = readuintval(ObjMap["GroupMask"]); - material = ObjMap["Material"].AsInteger(); - next_owner_mask = readuintval(ObjMap["NextOwnerMask"]); - p_code = ObjMap["PCode"].AsInteger(); - - if (ObjMap.ContainsKey("Path")) - { - if (ObjMap["Path"].Type != OSDType.Map) - { - responsedata["str_response_string"] = "Has Path key, but data not in expected format"; - return responsedata; - } - - OSDMap PathMap = (OSDMap)ObjMap["Path"]; - path_begin = PathMap["Begin"].AsInteger(); - path_curve = PathMap["Curve"].AsInteger(); - path_end = PathMap["End"].AsInteger(); - path_radius_offset = PathMap["RadiusOffset"].AsInteger(); - path_revolutions = PathMap["Revolutions"].AsInteger(); - path_scale_x = PathMap["ScaleX"].AsInteger(); - path_scale_y = PathMap["ScaleY"].AsInteger(); - path_shear_x = PathMap["ShearX"].AsInteger(); - path_shear_y = PathMap["ShearY"].AsInteger(); - path_skew = PathMap["Skew"].AsInteger(); - path_taper_x = PathMap["TaperX"].AsInteger(); - path_taper_y = PathMap["TaperY"].AsInteger(); - path_twist = PathMap["Twist"].AsInteger(); - path_twist_begin = PathMap["TwistBegin"].AsInteger(); - - } - - if (ObjMap.ContainsKey("Profile")) - { - if (ObjMap["Profile"].Type != OSDType.Map) - { - responsedata["str_response_string"] = "Has Profile key, but data not in expected format"; - return responsedata; - } - - OSDMap ProfileMap = (OSDMap)ObjMap["Profile"]; - - profile_begin = ProfileMap["Begin"].AsInteger(); - profile_curve = ProfileMap["Curve"].AsInteger(); - profile_end = ProfileMap["End"].AsInteger(); - hollow = ProfileMap["Hollow"].AsInteger(); - } - ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean(); - - ray_target_id = ObjMap["RayTargetId"].AsUUID(); - state = ObjMap["State"].AsInteger(); - try - { - ray_end = ((OSDArray) ObjMap["RayEnd"]).AsVector3(); - ray_start = ((OSDArray) ObjMap["RayStart"]).AsVector3(); - scale = ((OSDArray) ObjMap["Scale"]).AsVector3(); - rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion(); - } - catch (Exception) - { - responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format"; - return responsedata; - } - - if (rm.ContainsKey("AgentData")) - { - if (rm["AgentData"].Type != OSDType.Map) - { - responsedata["str_response_string"] = "Has AgentData key, but data not in expected format"; - return responsedata; - } - - OSDMap AgentDataMap = (OSDMap) rm["AgentData"]; - - //session_id = AgentDataMap["SessionId"].AsUUID(); - group_id = AgentDataMap["GroupId"].AsUUID(); - } - - } - else - { //v1 - bypass_raycast = rm["bypass_raycast"].AsBoolean(); - - everyone_mask = readuintval(rm["everyone_mask"]); - flags = readuintval(rm["flags"]); - group_id = rm["group_id"].AsUUID(); - group_mask = readuintval(rm["group_mask"]); - hollow = rm["hollow"].AsInteger(); - material = rm["material"].AsInteger(); - next_owner_mask = readuintval(rm["next_owner_mask"]); - hollow = rm["hollow"].AsInteger(); - p_code = rm["p_code"].AsInteger(); - path_begin = rm["path_begin"].AsInteger(); - path_curve = rm["path_curve"].AsInteger(); - path_end = rm["path_end"].AsInteger(); - path_radius_offset = rm["path_radius_offset"].AsInteger(); - path_revolutions = rm["path_revolutions"].AsInteger(); - path_scale_x = rm["path_scale_x"].AsInteger(); - path_scale_y = rm["path_scale_y"].AsInteger(); - path_shear_x = rm["path_shear_x"].AsInteger(); - path_shear_y = rm["path_shear_y"].AsInteger(); - path_skew = rm["path_skew"].AsInteger(); - path_taper_x = rm["path_taper_x"].AsInteger(); - path_taper_y = rm["path_taper_y"].AsInteger(); - path_twist = rm["path_twist"].AsInteger(); - path_twist_begin = rm["path_twist_begin"].AsInteger(); - profile_begin = rm["profile_begin"].AsInteger(); - profile_curve = rm["profile_curve"].AsInteger(); - profile_end = rm["profile_end"].AsInteger(); - - ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean(); - - ray_target_id = rm["ray_target_id"].AsUUID(); - - - //session_id = rm["session_id"].AsUUID(); - state = rm["state"].AsInteger(); - try - { - ray_end = ((OSDArray)rm["ray_end"]).AsVector3(); - ray_start = ((OSDArray)rm["ray_start"]).AsVector3(); - rotation = ((OSDArray)rm["rotation"]).AsQuaternion(); - scale = ((OSDArray)rm["scale"]).AsVector3(); - } - catch (Exception) - { - responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format"; - return responsedata; - } - } - - - - Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false); - - PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); - - pbs.PathBegin = (ushort)path_begin; - pbs.PathCurve = (byte)path_curve; - pbs.PathEnd = (ushort)path_end; - pbs.PathRadiusOffset = (sbyte)path_radius_offset; - pbs.PathRevolutions = (byte)path_revolutions; - pbs.PathScaleX = (byte)path_scale_x; - pbs.PathScaleY = (byte)path_scale_y; - pbs.PathShearX = (byte) path_shear_x; - pbs.PathShearY = (byte)path_shear_y; - pbs.PathSkew = (sbyte)path_skew; - pbs.PathTaperX = (sbyte)path_taper_x; - pbs.PathTaperY = (sbyte)path_taper_y; - pbs.PathTwist = (sbyte)path_twist; - pbs.PathTwistBegin = (sbyte)path_twist_begin; - pbs.HollowShape = (HollowShape) hollow; - pbs.PCode = (byte)p_code; - pbs.ProfileBegin = (ushort) profile_begin; - pbs.ProfileCurve = (byte) profile_curve; - pbs.ProfileEnd = (ushort)profile_end; - pbs.Scale = scale; - pbs.State = (byte)state; - - SceneObjectGroup obj = null; ; - - if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos)) - { - // rez ON the ground, not IN the ground - pos.Z += 0.25F; - - obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs); - } - - - if (obj == null) - return responsedata; - - SceneObjectPart rootpart = obj.RootPart; - rootpart.Shape = pbs; - rootpart.Flags |= (PrimFlags)flags; - rootpart.EveryoneMask = everyone_mask; - rootpart.GroupID = group_id; - rootpart.GroupMask = group_mask; - rootpart.NextOwnerMask = next_owner_mask; - rootpart.Material = (byte)material; - - - - m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor); - - responsedata["int_response_code"] = 200; //501; //410; //404; - responsedata["content_type"] = "text/plain"; - responsedata["keepalive"] = false; - responsedata["str_response_string"] = String.Format("local_id{0}",ConvertUintToBytes(obj.LocalId)); - - return responsedata; - } - - private uint readuintval(OSD obj) - { - byte[] tmp = obj.AsBinary(); - if (BitConverter.IsLittleEndian) - Array.Reverse(tmp); - return Utils.BytesToUInt(tmp); - - } - private string ConvertUintToBytes(uint val) - { - byte[] resultbytes = Utils.UIntToBytes(val); - if (BitConverter.IsLittleEndian) - Array.Reverse(resultbytes); - return String.Format("{0}",Convert.ToBase64String(resultbytes)); - } - - public void Close() - { - - } - - public string Name - { - get { return "ObjectAddModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs deleted file mode 100644 index a7e9849..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Globalization; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Profiles -{ - public class AvatarProfilesModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Scene m_scene; - - public AvatarProfilesModule() - { - } - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_scene.EventManager.OnNewClient += NewClient; - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "AvatarProfilesModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - public void NewClient(IClientAPI client) - { - client.OnRequestAvatarProperties += RequestAvatarProperty; - client.OnUpdateAvatarProperties += UpdateAvatarProperties; - } - - public void RemoveClient(IClientAPI client) - { - client.OnRequestAvatarProperties -= RequestAvatarProperty; - client.OnUpdateAvatarProperties -= UpdateAvatarProperties; - } - - /// - /// - /// - /// - /// - public void RequestAvatarProperty(IClientAPI remoteClient, UUID avatarID) - { - // FIXME: finish adding fields such as url, masking, etc. - UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID); - if (null != profile) - { - Byte[] charterMember; - if (profile.CustomType == "") - { - charterMember = new Byte[1]; - charterMember[0] = (Byte)((profile.UserFlags & 0xf00) >> 8); - } - else - { - charterMember = Utils.StringToBytes(profile.CustomType); - } - - remoteClient.SendAvatarProperties(profile.ID, profile.AboutText, - Util.ToDateTime(profile.Created).ToString("M/d/yyyy", CultureInfo.InvariantCulture), - charterMember, profile.FirstLifeAboutText, (uint)(profile.UserFlags & 0xff), - profile.FirstLifeImage, profile.Image, String.Empty, profile.Partner); - } - else - { - m_log.Debug("[AvatarProfilesModule]: Got null for profile for " + avatarID.ToString()); - } - } - - public void UpdateAvatarProperties(IClientAPI remoteClient, UserProfileData newProfile) - { - UserProfileData Profile = m_scene.CommsManager.UserService.GetUserProfile(newProfile.ID); - - // if it's the profile of the user requesting the update, then we change only a few things. - if (remoteClient.AgentId.CompareTo(Profile.ID) == 0) - { - Profile.Image = newProfile.Image; - Profile.FirstLifeImage = newProfile.FirstLifeImage; - Profile.AboutText = newProfile.AboutText; - Profile.FirstLifeAboutText = newProfile.FirstLifeAboutText; - } - else - { - return; - } - - if (m_scene.CommsManager.UserService.UpdateUserProfile(Profile)) - { - RequestAvatarProperty(remoteClient, newProfile.ID); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs deleted file mode 100644 index 33d7135..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Communications.Capabilities; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Caps=OpenSim.Framework.Communications.Capabilities.Caps; - -namespace OpenSim.Region.Environment.Modules.Avatar.Voice.AsterixVoice -{ - public class AsteriskVoiceModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; - private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; - - private string m_asterisk; - private string m_asterisk_password; - private string m_asterisk_salt; - private int m_asterisk_timeout; - private string m_confDomain; - private IConfig m_config; - private Scene m_scene; - private string m_sipDomain; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_config = config.Configs["AsteriskVoice"]; - - if (null == m_config) - { - m_log.Info("[ASTERISKVOICE] no config found, plugin disabled"); - return; - } - - if (!m_config.GetBoolean("enabled", false)) - { - m_log.Info("[ASTERISKVOICE] plugin disabled by configuration"); - return; - } - m_log.Info("[ASTERISKVOICE] plugin enabled"); - - try - { - m_sipDomain = m_config.GetString("sip_domain", String.Empty); - m_log.InfoFormat("[ASTERISKVOICE] using SIP domain {0}", m_sipDomain); - - m_confDomain = m_config.GetString("conf_domain", String.Empty); - m_log.InfoFormat("[ASTERISKVOICE] using conf domain {0}", m_confDomain); - - m_asterisk = m_config.GetString("asterisk_frontend", String.Empty); - m_asterisk_password = m_config.GetString("asterisk_password", String.Empty); - m_asterisk_timeout = m_config.GetInt("asterisk_timeout", 3000); - m_asterisk_salt = m_config.GetString("asterisk_salt", "Wuffwuff"); - if (String.IsNullOrEmpty(m_asterisk)) throw new Exception("missing asterisk_frontend config parameter"); - if (String.IsNullOrEmpty(m_asterisk_password)) throw new Exception("missing asterisk_password config parameter"); - m_log.InfoFormat("[ASTERISKVOICE] using asterisk front end {0}", m_asterisk); - - scene.EventManager.OnRegisterCaps += OnRegisterCaps; - } - catch (Exception e) - { - m_log.ErrorFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.Message); - m_log.DebugFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.ToString()); - return; - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "AsteriskVoiceModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - public void OnRegisterCaps(UUID agentID, Caps caps) - { - m_log.DebugFormat("[ASTERISKVOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); - string capsBase = "/CAPS/" + caps.CapsObjectPath; - caps.RegisterHandler("ParcelVoiceInfoRequest", - new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, - delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return ParcelVoiceInfoRequest(request, path, param, - agentID, caps); - })); - caps.RegisterHandler("ProvisionVoiceAccountRequest", - new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, - delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return ProvisionVoiceAccountRequest(request, path, param, - agentID, caps); - })); - } - - /// - /// Callback for a client request for ParcelVoiceInfo - /// - /// - /// - /// - /// - /// - /// - public string ParcelVoiceInfoRequest(string request, string path, string param, - UUID agentID, Caps caps) - { - // we need to do: - // - send channel_uri: as "sip:regionID@m_sipDomain" - try - { - m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", - request, path, param); - - - // setup response to client - Hashtable creds = new Hashtable(); - creds["channel_uri"] = String.Format("sip:{0}@{1}", - m_scene.RegionInfo.RegionID, m_sipDomain); - - string regionName = m_scene.RegionInfo.RegionName; - ScenePresence avatar = m_scene.GetScenePresence(agentID); - if (null == m_scene.LandChannel) throw new Exception("land data not yet available"); - LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); - - LLSDParcelVoiceInfoResponse parcelVoiceInfo = - new LLSDParcelVoiceInfoResponse(regionName, land.LocalID, creds); - - string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); - - - // update region on asterisk-opensim frontend - Hashtable requestData = new Hashtable(); - requestData["admin_password"] = m_asterisk_password; - requestData["region"] = m_scene.RegionInfo.RegionID.ToString(); - if (!String.IsNullOrEmpty(m_confDomain)) - { - requestData["region"] += String.Format("@{0}", m_confDomain); - } - - ArrayList SendParams = new ArrayList(); - SendParams.Add(requestData); - XmlRpcRequest updateAccountRequest = new XmlRpcRequest("region_update", SendParams); - XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout); - Hashtable responseData = (Hashtable) updateAccountResponse.Value; - - if (!responseData.ContainsKey("success")) throw new Exception("region_update call failed"); - - bool success = Convert.ToBoolean((string) responseData["success"]); - if (!success) throw new Exception("region_update failed"); - - - m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: {0}", r); - return r; - } - catch (Exception e) - { - m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0}, retry later", e.Message); - m_log.DebugFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0} failed", e.ToString()); - - return "undef"; - } - } - - /// - /// Callback for a client request for Voice Account Details - /// - /// - /// - /// - /// - /// - /// - public string ProvisionVoiceAccountRequest(string request, string path, string param, - UUID agentID, Caps caps) - { - // we need to - // - get user data from UserProfileCacheService - // - generate nonce for user voice account password - // - issue XmlRpc request to asterisk opensim front end: - // + user: base 64 encoded user name (otherwise SL - // client is unhappy) - // + password: nonce - // - the XmlRpc call to asteris-opensim was successful: - // send account details back to client - try - { - m_log.DebugFormat("[ASTERISKVOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", - request, path, param); - - // get user data & prepare voice account response - string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes()); - voiceUser = voiceUser.Replace('+', '-').Replace('/', '_'); - - CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); - if (null == userInfo) throw new Exception("cannot get user details"); - - // we generate a nonce everytime - string voicePassword = "$1$" + Util.Md5Hash(DateTime.UtcNow.ToLongTimeString() + m_asterisk_salt); - LLSDVoiceAccountResponse voiceAccountResponse = - new LLSDVoiceAccountResponse(voiceUser, voicePassword); - string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); - m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r); - - - // update user account on asterisk frontend - Hashtable requestData = new Hashtable(); - requestData["admin_password"] = m_asterisk_password; - requestData["username"] = voiceUser; - if (!String.IsNullOrEmpty(m_sipDomain)) - { - requestData["username"] += String.Format("@{0}", m_sipDomain); - } - requestData["password"] = voicePassword; - - ArrayList SendParams = new ArrayList(); - SendParams.Add(requestData); - XmlRpcRequest updateAccountRequest = new XmlRpcRequest("account_update", SendParams); - XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout); - Hashtable responseData = (Hashtable) updateAccountResponse.Value; - - if (!responseData.ContainsKey("success")) throw new Exception("account_update call failed"); - - bool success = Convert.ToBoolean((string) responseData["success"]); - if (!success) throw new Exception("account_update failed"); - - return r; - } - catch (Exception e) - { - m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0}, retry later", e.Message); - m_log.DebugFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0} failed", e.ToString()); - - return "undef"; - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs deleted file mode 100644 index e4d9b7c..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Communications.Capabilities; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Caps=OpenSim.Framework.Communications.Capabilities.Caps; - -namespace OpenSim.Region.Environment.Modules.Avatar.Voice.SIPVoice -{ - public class SIPVoiceModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; - private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; - private IConfig m_config; - private Scene m_scene; - private string m_sipDomain; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_config = config.Configs["Voice"]; - - if (null == m_config || !m_config.GetBoolean("enabled", false)) - { - m_log.Info("[VOICE] plugin disabled"); - return; - } - m_log.Info("[VOICE] plugin enabled"); - - m_sipDomain = m_config.GetString("sip_domain", String.Empty); - if (String.IsNullOrEmpty(m_sipDomain)) - { - m_log.Error("[VOICE] plugin mis-configured: missing sip_domain configuration"); - m_log.Info("[VOICE] plugin disabled"); - return; - } - m_log.InfoFormat("[VOICE] using SIP domain {0}", m_sipDomain); - - scene.EventManager.OnRegisterCaps += OnRegisterCaps; - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "VoiceModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - public void OnRegisterCaps(UUID agentID, Caps caps) - { - m_log.DebugFormat("[VOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); - string capsBase = "/CAPS/" + caps.CapsObjectPath; - caps.RegisterHandler("ParcelVoiceInfoRequest", - new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, - delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return ParcelVoiceInfoRequest(request, path, param, - agentID, caps); - })); - caps.RegisterHandler("ProvisionVoiceAccountRequest", - new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, - delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return ProvisionVoiceAccountRequest(request, path, param, - agentID, caps); - })); - } - - /// - /// Callback for a client request for ParcelVoiceInfo - /// - /// - /// - /// - /// - /// - /// - public string ParcelVoiceInfoRequest(string request, string path, string param, - UUID agentID, Caps caps) - { - try - { - m_log.DebugFormat("[VOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", request, path, param); - - // FIXME: get the creds from region file or from config - Hashtable creds = new Hashtable(); - - creds["channel_uri"] = String.Format("sip:{0}@{1}", agentID, m_sipDomain); - - string regionName = m_scene.RegionInfo.RegionName; - ScenePresence avatar = m_scene.GetScenePresence(agentID); - if (null == m_scene.LandChannel) throw new Exception("land data not yet available"); - LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); - - LLSDParcelVoiceInfoResponse parcelVoiceInfo = - new LLSDParcelVoiceInfoResponse(regionName, land.LocalID, creds); - - string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); - m_log.DebugFormat("[VOICE][PARCELVOICE]: {0}", r); - - return r; - } - catch (Exception e) - { - m_log.ErrorFormat("[CAPS]: {0}, try again later", e.ToString()); - } - - return null; - } - - /// - /// Callback for a client request for Voice Account Details - /// - /// - /// - /// - /// - /// - /// - public string ProvisionVoiceAccountRequest(string request, string path, string param, - UUID agentID, Caps caps) - { - try - { - m_log.DebugFormat("[VOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", - request, path, param); - - string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes()); - voiceUser = voiceUser.Replace('+', '-').Replace('/', '_'); - - CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); - if (null == userInfo) throw new Exception("cannot get user details"); - - LLSDVoiceAccountResponse voiceAccountResponse = - new LLSDVoiceAccountResponse(voiceUser, "$1$" + userInfo.UserProfile.PasswordHash); - string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); - m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r); - return r; - } - catch (Exception e) - { - m_log.ErrorFormat("[CAPS][PROVISIONVOICE]: {0}, retry later", e.Message); - } - - return null; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs b/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs deleted file mode 100644 index 33ccbf4..0000000 --- a/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Threading; -using System.Xml; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Communications.Local -{ - public class LocalInterregionComms : IRegionModule, IInterregionCommsOut, IInterregionCommsIn - { - private bool m_enabled = false; - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private List m_sceneList = new List(); - - #region Events - public event ChildAgentUpdateReceived OnChildAgentUpdate; - - #endregion /* Events */ - - #region IRegionModule - - public void Initialise(Scene scene, IConfigSource config) - { - if (m_sceneList.Count == 0) - { - IConfig startupConfig = config.Configs["Communications"]; - - if ((startupConfig != null) && (startupConfig.GetString("InterregionComms", "RESTCommms") == "LocalComms")) - { - m_log.Debug("[LOCAL COMMS]: Enabling InterregionComms LocalComms module"); - m_enabled = true; - } - } - - if (!m_enabled) - return; - - Init(scene); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "LocalInterregionCommsModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - /// - /// Can be called from other modules. - /// - /// - public void Init(Scene scene) - { - if (!m_sceneList.Contains(scene)) - { - lock (m_sceneList) - { - m_sceneList.Add(scene); - if (m_enabled) - scene.RegisterModuleInterface(this); - scene.RegisterModuleInterface(this); - } - - } - } - - #endregion /* IRegionModule */ - - #region IInterregionComms - - /** - * Agent-related communications - */ - - public bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit) - { - foreach (Scene s in m_sceneList) - { - if (s.RegionInfo.RegionHandle == regionHandle) - { -// m_log.DebugFormat("[LOCAL COMMS]: Found region {0} to send SendCreateChildAgent", regionHandle); - s.NewUserConnection(aCircuit); - return true; - } - } - -// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for SendCreateChildAgent", regionHandle); - return false; - } - - public bool SendChildAgentUpdate(ulong regionHandle, AgentData cAgentData) - { - foreach (Scene s in m_sceneList) - { - if (s.RegionInfo.RegionHandle == regionHandle) - { - //m_log.DebugFormat( - // "[LOCAL COMMS]: Found region {0} {1} to send ChildAgentUpdate", - // s.RegionInfo.RegionName, regionHandle); - - s.IncomingChildAgentDataUpdate(cAgentData); - return true; - } - } - -// m_log.DebugFormat("[LOCAL COMMS]: Did not find region {0} for ChildAgentUpdate", regionHandle); - return false; - } - - public bool SendChildAgentUpdate(ulong regionHandle, AgentPosition cAgentData) - { - foreach (Scene s in m_sceneList) - { - if (s.RegionInfo.RegionHandle == regionHandle) - { - //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); - s.IncomingChildAgentDataUpdate(cAgentData); - return true; - } - } - //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); - return false; - } - - public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri) - { - //uint x, y; - //Utils.LongToUInts(regionHandle, out x, out y); - //x = x / Constants.RegionSize; - //y = y / Constants.RegionSize; - //Console.WriteLine("\n >>> Local SendReleaseAgent " + x + "-" + y); - foreach (Scene s in m_sceneList) - { - if (s.RegionInfo.RegionHandle == regionHandle) - { - //m_log.Debug("[LOCAL COMMS]: Found region to SendReleaseAgent"); - return s.IncomingReleaseAgent(id); - } - } - //m_log.Debug("[LOCAL COMMS]: region not found in SendReleaseAgent"); - return false; - } - - public bool SendCloseAgent(ulong regionHandle, UUID id) - { - //uint x, y; - //Utils.LongToUInts(regionHandle, out x, out y); - //x = x / Constants.RegionSize; - //y = y / Constants.RegionSize; - //Console.WriteLine("\n >>> Local SendCloseAgent " + x + "-" + y); - foreach (Scene s in m_sceneList) - { - if (s.RegionInfo.RegionHandle == regionHandle) - { - //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent"); - return s.IncomingCloseAgent(id); - } - } - //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); - return false; - } - - /** - * Object-related communications - */ - - public bool SendCreateObject(ulong regionHandle, ISceneObject sog) - { - foreach (Scene s in m_sceneList) - { - if (s.RegionInfo.RegionHandle == regionHandle) - { - //m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); - return s.IncomingCreateObject(sog); - } - } - return false; - } - - #endregion /* IInterregionComms */ - - #region Misc - - public UUID GetRegionID(ulong regionhandle) - { - foreach (Scene s in m_sceneList) - { - if (s.RegionInfo.RegionHandle == regionhandle) - return s.RegionInfo.RegionID; - } - // ? weird. should not happen - return m_sceneList[0].RegionInfo.RegionID; - } - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs b/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs deleted file mode 100644 index 95b95ee..0000000 --- a/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs +++ /dev/null @@ -1,960 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Threading; -using System.Xml; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Hypergrid; -using OpenSim.Region.Environment.Modules.Communications.Local; - -namespace OpenSim.Region.Environment.Modules.Communications.REST -{ - public class RESTInterregionComms : IRegionModule, IInterregionCommsOut - { - private static bool initialized = false; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected bool m_enabled = false; - protected Scene m_aScene; - // RESTInterregionComms does not care about local regions; it delegates that to the Local module - protected LocalInterregionComms m_localBackend; - - protected CommunicationsManager m_commsManager; - - #region IRegionModule - - public virtual void Initialise(Scene scene, IConfigSource config) - { - if (!initialized) - { - initialized = true; - IConfig startupConfig = config.Configs["Communications"]; - - if ((startupConfig == null) - || (startupConfig != null) - && (startupConfig.GetString("InterregionComms", "RESTComms") == "RESTComms")) - { - m_log.Info("[REST COMMS]: Enabling InterregionComms RESTComms module"); - m_enabled = true; - InitOnce(scene); - } - } - - if (!m_enabled) - return; - - InitEach(scene); - - } - - public virtual void PostInitialise() - { - if (m_enabled) - AddHTTPHandlers(); - } - - public virtual void Close() - { - } - - public virtual string Name - { - get { return "RESTInterregionCommsModule"; } - } - - public virtual bool IsSharedModule - { - get { return true; } - } - - protected virtual void InitEach(Scene scene) - { - m_localBackend.Init(scene); - scene.RegisterModuleInterface(this); - } - - protected virtual void InitOnce(Scene scene) - { - m_localBackend = new LocalInterregionComms(); - m_commsManager = scene.CommsManager; - m_aScene = scene; - } - - protected virtual void AddHTTPHandlers() - { - m_aScene.CommsManager.HttpServer.AddHTTPHandler("/agent/", AgentHandler); - m_aScene.CommsManager.HttpServer.AddHTTPHandler("/object/", ObjectHandler); - } - - #endregion /* IRegionModule */ - - #region IInterregionComms - - /** - * Agent-related communications - */ - - public bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit) - { - // Try local first - if (m_localBackend.SendCreateChildAgent(regionHandle, aCircuit)) - return true; - - // else do the remote thing - RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); - if (regInfo != null) - { - SendUserInformation(regInfo, aCircuit); - - return DoCreateChildAgentCall(regInfo, aCircuit); - } - //else - // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); - return false; - } - - public bool SendChildAgentUpdate(ulong regionHandle, AgentData cAgentData) - { - // Try local first - if (m_localBackend.SendChildAgentUpdate(regionHandle, cAgentData)) - return true; - - // else do the remote thing - RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); - if (regInfo != null) - { - return DoChildAgentUpdateCall(regInfo, cAgentData); - } - //else - // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); - return false; - - } - - public bool SendChildAgentUpdate(ulong regionHandle, AgentPosition cAgentData) - { - // Try local first - if (m_localBackend.SendChildAgentUpdate(regionHandle, cAgentData)) - return true; - - // else do the remote thing - RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); - if (regInfo != null) - { - return DoChildAgentUpdateCall(regInfo, cAgentData); - } - //else - // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); - return false; - - } - - public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri) - { - // Try local first - if (m_localBackend.SendReleaseAgent(regionHandle, id, uri)) - return true; - - // else do the remote thing - return DoReleaseAgentCall(regionHandle, id, uri); - } - - public bool SendCloseAgent(ulong regionHandle, UUID id) - { - // Try local first - if (m_localBackend.SendCloseAgent(regionHandle, id)) - return true; - - // else do the remote thing - RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); - if (regInfo != null) - { - return DoCloseAgentCall(regInfo, id); - } - //else - // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); - return false; - } - - /** - * Object-related communications - */ - - public bool SendCreateObject(ulong regionHandle, ISceneObject sog) - { - // Try local first - ISceneObject sogClone = sog.CloneForNewScene(); - if (m_localBackend.SendCreateObject(regionHandle, sogClone)) - { - //m_log.Debug("[REST COMMS]: LocalBackEnd SendCreateObject succeeded"); - return true; - } - - // else do the remote thing - RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); - if (regInfo != null) - { - return DoCreateObjectCall(regInfo, sog); - } - //else - // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); - return false; - } - - #endregion /* IInterregionComms */ - - #region DoWork functions for the above public interface - - //------------------------------------------------------------------- - // Internal functions for the above public interface - //------------------------------------------------------------------- - - protected bool DoCreateChildAgentCall(RegionInfo region, AgentCircuitData aCircuit) - { - // Eventually, we want to use a caps url instead of the agentID - string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + aCircuit.AgentID + "/"; - //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); - - WebRequest AgentCreateRequest = WebRequest.Create(uri); - AgentCreateRequest.Method = "POST"; - AgentCreateRequest.ContentType = "application/json"; - AgentCreateRequest.Timeout = 10000; - - // Fill it in - OSDMap args = null; - try - { - args = aCircuit.PackAgentCircuitData(); - } - catch (Exception e) - { - m_log.Debug("[REST COMMS]: PackAgentCircuitData failed with exception: " + e.Message); - } - // Add the regionhandle of the destination region - ulong regionHandle = GetRegionHandle(region.RegionHandle); - args["destination_handle"] = OSD.FromString(regionHandle.ToString()); - - string strBuffer = ""; - byte[] buffer = new byte[1]; - try - { - strBuffer = OSDParser.SerializeJsonString(args); - System.Text.UTF8Encoding str = new System.Text.UTF8Encoding(); - buffer = str.GetBytes(strBuffer); - - } - catch (Exception e) - { - m_log.WarnFormat("[OSG2]: Exception thrown on serialization of ChildCreate: {0}", e.Message); - // ignore. buffer will be empty, caller should check. - } - - Stream os = null; - try - { // send the Post - AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send - os = AgentCreateRequest.GetRequestStream(); - os.Write(buffer, 0, strBuffer.Length); //Send it - os.Close(); - //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri); - } - //catch (WebException ex) - catch - { - //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message); - - return false; - } - - // Let's wait for the response - //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); - - try - { - WebResponse webResponse = AgentCreateRequest.GetResponse(); - if (webResponse == null) - { - m_log.Info("[REST COMMS]: Null reply on DoCreateChildAgentCall post"); - } - - StreamReader sr = new StreamReader(webResponse.GetResponseStream()); - //reply = sr.ReadToEnd().Trim(); - sr.ReadToEnd().Trim(); - sr.Close(); - //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply); - - } - catch (WebException ex) - { - m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); - // ignore, really - } - - return true; - - } - - protected bool DoChildAgentUpdateCall(RegionInfo region, IAgentData cAgentData) - { - // Eventually, we want to use a caps url instead of the agentID - string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + cAgentData.AgentID + "/"; - //Console.WriteLine(" >>> DoChildAgentUpdateCall <<< " + uri); - - WebRequest ChildUpdateRequest = WebRequest.Create(uri); - ChildUpdateRequest.Method = "PUT"; - ChildUpdateRequest.ContentType = "application/json"; - ChildUpdateRequest.Timeout = 10000; - - // Fill it in - OSDMap args = null; - try - { - args = cAgentData.PackUpdateMessage(); - } - catch (Exception e) - { - m_log.Debug("[REST COMMS]: PackUpdateMessage failed with exception: " + e.Message); - } - // Add the regionhandle of the destination region - ulong regionHandle = GetRegionHandle(region.RegionHandle); - args["destination_handle"] = OSD.FromString(regionHandle.ToString()); - - string strBuffer = ""; - byte[] buffer = new byte[1]; - try - { - strBuffer = OSDParser.SerializeJsonString(args); - System.Text.UTF8Encoding str = new System.Text.UTF8Encoding(); - buffer = str.GetBytes(strBuffer); - - } - catch (Exception e) - { - m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildUpdate: {0}", e.Message); - // ignore. buffer will be empty, caller should check. - } - - Stream os = null; - try - { // send the Post - ChildUpdateRequest.ContentLength = buffer.Length; //Count bytes to send - os = ChildUpdateRequest.GetRequestStream(); - os.Write(buffer, 0, strBuffer.Length); //Send it - os.Close(); - //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri); - } - //catch (WebException ex) - catch - { - //m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message); - - return false; - } - - // Let's wait for the response - //m_log.Info("[REST COMMS]: Waiting for a reply after ChildAgentUpdate"); - - try - { - WebResponse webResponse = ChildUpdateRequest.GetResponse(); - if (webResponse == null) - { - m_log.Info("[REST COMMS]: Null reply on ChilAgentUpdate post"); - } - - StreamReader sr = new StreamReader(webResponse.GetResponseStream()); - //reply = sr.ReadToEnd().Trim(); - sr.ReadToEnd().Trim(); - sr.Close(); - //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); - - } - catch (WebException ex) - { - m_log.InfoFormat("[REST COMMS]: exception on reply of ChilAgentUpdate {0}", ex.Message); - // ignore, really - } - - return true; - } - - protected bool DoReleaseAgentCall(ulong regionHandle, UUID id, string uri) - { - //Console.WriteLine(" >>> DoReleaseAgentCall <<< " + uri); - - WebRequest request = WebRequest.Create(uri); - request.Method = "DELETE"; - request.Timeout = 10000; - - try - { - WebResponse webResponse = request.GetResponse(); - if (webResponse == null) - { - m_log.Info("[REST COMMS]: Null reply on agent get "); - } - - StreamReader sr = new StreamReader(webResponse.GetResponseStream()); - //reply = sr.ReadToEnd().Trim(); - sr.ReadToEnd().Trim(); - sr.Close(); - //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); - - } - catch (WebException ex) - { - m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message); - // ignore, really - } - - return true; - } - - protected bool DoCloseAgentCall(RegionInfo region, UUID id) - { - string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() +"/"; - - //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); - - WebRequest request = WebRequest.Create(uri); - request.Method = "DELETE"; - request.Timeout = 10000; - - try - { - WebResponse webResponse = request.GetResponse(); - if (webResponse == null) - { - m_log.Info("[REST COMMS]: Null reply on agent get "); - } - - StreamReader sr = new StreamReader(webResponse.GetResponseStream()); - //reply = sr.ReadToEnd().Trim(); - sr.ReadToEnd().Trim(); - sr.Close(); - //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); - - } - catch (WebException ex) - { - m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message); - // ignore, really - } - - return true; - } - - protected bool DoCreateObjectCall(RegionInfo region, ISceneObject sog) - { - ulong regionHandle = GetRegionHandle(region.RegionHandle); - string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/object/" + sog.UUID + "/" + regionHandle.ToString() + "/"; - //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); - - WebRequest ObjectCreateRequest = WebRequest.Create(uri); - ObjectCreateRequest.Method = "POST"; - ObjectCreateRequest.ContentType = "text/xml"; - ObjectCreateRequest.Timeout = 10000; - - OSDMap args = new OSDMap(2); - args["sog"] = OSD.FromString(sog.ToXmlString2()); - args["extra"] = OSD.FromString(sog.ExtraToXmlString()); - if (m_aScene.m_allowScriptCrossings) - { - string state = sog.GetStateSnapshot(); - if (state.Length > 0) - args["state"] = OSD.FromString(state); - } - - string strBuffer = ""; - byte[] buffer = new byte[1]; - try - { - strBuffer = OSDParser.SerializeJsonString(args); - System.Text.UTF8Encoding str = new System.Text.UTF8Encoding(); - buffer = str.GetBytes(strBuffer); - - } - catch (Exception e) - { - m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of CreateObject: {0}", e.Message); - // ignore. buffer will be empty, caller should check. - } - - Stream os = null; - try - { // send the Post - ObjectCreateRequest.ContentLength = buffer.Length; //Count bytes to send - os = ObjectCreateRequest.GetRequestStream(); - os.Write(buffer, 0, strBuffer.Length); //Send it - os.Close(); - m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri); - } - //catch (WebException ex) - catch - { - // m_log.InfoFormat("[REST COMMS]: Bad send on CreateObject {0}", ex.Message); - - return false; - } - - // Let's wait for the response - //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); - - try - { - WebResponse webResponse = ObjectCreateRequest.GetResponse(); - if (webResponse == null) - { - m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post"); - } - - StreamReader sr = new StreamReader(webResponse.GetResponseStream()); - //reply = sr.ReadToEnd().Trim(); - sr.ReadToEnd().Trim(); - sr.Close(); - //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply); - - } - catch (WebException ex) - { - m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message); - // ignore, really - } - - return true; - - } - - #endregion /* Do Work */ - - #region Incoming calls from remote instances - - /** - * Agent-related incoming calls - */ - - public Hashtable AgentHandler(Hashtable request) - { - //m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called"); - - //Console.WriteLine("---------------------------"); - //Console.WriteLine(" >> uri=" + request["uri"]); - //Console.WriteLine(" >> content-type=" + request["content-type"]); - //Console.WriteLine(" >> http-method=" + request["http-method"]); - //Console.WriteLine("---------------------------\n"); - - Hashtable responsedata = new Hashtable(); - responsedata["content_type"] = "text/html"; - - UUID agentID; - string action; - ulong regionHandle; - if (!GetParams((string)request["uri"], out agentID, out regionHandle, out action)) - { - m_log.InfoFormat("[REST COMMS]: Invalid parameters for agent message {0}", request["uri"]); - responsedata["int_response_code"] = 404; - responsedata["str_response_string"] = "false"; - - return responsedata; - } - - // Next, let's parse the verb - string method = (string)request["http-method"]; - if (method.Equals("PUT")) - { - DoAgentPut(request, responsedata); - return responsedata; - } - else if (method.Equals("POST")) - { - DoAgentPost(request, responsedata, agentID); - return responsedata; - } - else if (method.Equals("DELETE")) - { - DoAgentDelete(request, responsedata, agentID, action, regionHandle); - - return responsedata; - } - else - { - m_log.InfoFormat("[REST COMMS]: method {0} not supported in agent message", method); - responsedata["int_response_code"] = 404; - responsedata["str_response_string"] = "false"; - - return responsedata; - } - - } - - protected OSDMap GetOSDMap(Hashtable request) - { - OSDMap args = null; - try - { - OSD buffer; - // We should pay attention to the content-type, but let's assume we know it's Json - buffer = OSDParser.DeserializeJson((string)request["body"]); - if (buffer.Type == OSDType.Map) - { - args = (OSDMap)buffer; - return args; - } - else - { - // uh? - m_log.Debug("[REST COMMS]: Got OSD of type " + buffer.Type.ToString()); - return null; - } - } - catch (Exception ex) - { - m_log.InfoFormat("[REST COMMS]: exception on parse of REST message {0}", ex.Message); - return null; - } - } - - protected virtual void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) - { - OSDMap args = GetOSDMap(request); - if (args == null) - { - responsedata["int_response_code"] = 400; - responsedata["str_response_string"] = "false"; - return; - } - - // retrieve the regionhandle - ulong regionhandle = 0; - if (args["destination_handle"] != null) - UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle); - - AgentCircuitData aCircuit = new AgentCircuitData(); - try - { - aCircuit.UnpackAgentCircuitData(args); - } - catch (Exception ex) - { - m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildCreate message {0}", ex.Message); - return; - } - - // This is the meaning of POST agent - AdjustUserInformation(aCircuit); - bool result = m_localBackend.SendCreateChildAgent(regionhandle, aCircuit); - - responsedata["int_response_code"] = 200; - responsedata["str_response_string"] = result.ToString(); - } - - protected virtual void DoAgentPut(Hashtable request, Hashtable responsedata) - { - OSDMap args = GetOSDMap(request); - if (args == null) - { - responsedata["int_response_code"] = 400; - responsedata["str_response_string"] = "false"; - return; - } - - // retrieve the regionhandle - ulong regionhandle = 0; - if (args["destination_handle"] != null) - UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle); - - string messageType; - if (args["message_type"] != null) - messageType = args["message_type"].AsString(); - else - { - m_log.Warn("[REST COMMS]: Agent Put Message Type not found. "); - messageType = "AgentData"; - } - - bool result = true; - if ("AgentData".Equals(messageType)) - { - AgentData agent = new AgentData(); - try - { - agent.UnpackUpdateMessage(args); - } - catch (Exception ex) - { - m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildAgentUpdate message {0}", ex.Message); - return; - } - //agent.Dump(); - // This is one of the meanings of PUT agent - result = m_localBackend.SendChildAgentUpdate(regionhandle, agent); - - } - else if ("AgentPosition".Equals(messageType)) - { - AgentPosition agent = new AgentPosition(); - try - { - agent.UnpackUpdateMessage(args); - } - catch (Exception ex) - { - m_log.InfoFormat("[REST COMMS]: exception on unpacking ChildAgentUpdate message {0}", ex.Message); - return; - } - //agent.Dump(); - // This is one of the meanings of PUT agent - result = m_localBackend.SendChildAgentUpdate(regionhandle, agent); - - } - - - - responsedata["int_response_code"] = 200; - responsedata["str_response_string"] = result.ToString(); - } - - protected virtual void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, ulong regionHandle) - { - //Console.WriteLine(" >>> DoDelete action:" + action + "; regionHandle:" + regionHandle); - - if (action.Equals("release")) - m_localBackend.SendReleaseAgent(regionHandle, id, ""); - else - m_localBackend.SendCloseAgent(regionHandle, id); - - responsedata["int_response_code"] = 200; - responsedata["str_response_string"] = "OpenSim agent " + id.ToString(); - } - - /** - * Object-related incoming calls - */ - - public Hashtable ObjectHandler(Hashtable request) - { - //m_log.Debug("[CONNECTION DEBUGGING]: ObjectHandler Called"); - - //Console.WriteLine("---------------------------"); - //Console.WriteLine(" >> uri=" + request["uri"]); - //Console.WriteLine(" >> content-type=" + request["content-type"]); - //Console.WriteLine(" >> http-method=" + request["http-method"]); - //Console.WriteLine("---------------------------\n"); - - Hashtable responsedata = new Hashtable(); - responsedata["content_type"] = "text/html"; - - UUID objectID; - string action; - ulong regionHandle; - if (!GetParams((string)request["uri"], out objectID, out regionHandle, out action)) - { - m_log.InfoFormat("[REST COMMS]: Invalid parameters for object message {0}", request["uri"]); - responsedata["int_response_code"] = 404; - responsedata["str_response_string"] = "false"; - - return responsedata; - } - - // Next, let's parse the verb - string method = (string)request["http-method"]; - if (method.Equals("POST")) - { - DoObjectPost(request, responsedata, regionHandle); - return responsedata; - } - //else if (method.Equals("PUT")) - //{ - // DoObjectPut(request, responsedata, agentID); - // return responsedata; - //} - //else if (method.Equals("DELETE")) - //{ - // DoObjectDelete(request, responsedata, agentID, action, regionHandle); - // return responsedata; - //} - else - { - m_log.InfoFormat("[REST COMMS]: method {0} not supported in object message", method); - responsedata["int_response_code"] = 404; - responsedata["str_response_string"] = "false"; - - return responsedata; - } - - } - - protected virtual void DoObjectPost(Hashtable request, Hashtable responsedata, ulong regionhandle) - { - OSDMap args = GetOSDMap(request); - if (args == null) - { - responsedata["int_response_code"] = 400; - responsedata["str_response_string"] = "false"; - return; - } - - string sogXmlStr = "", extraStr = "", stateXmlStr = ""; - if (args["sog"] != null) - sogXmlStr = args["sog"].AsString(); - if (args["extra"] != null) - extraStr = args["extra"].AsString(); - - UUID regionID = m_localBackend.GetRegionID(regionhandle); - SceneObjectGroup sog = null; - try - { - sog = new SceneObjectGroup(sogXmlStr); - sog.ExtraFromXmlString(extraStr); - } - catch (Exception ex) - { - m_log.InfoFormat("[REST COMMS]: exception on deserializing scene object {0}", ex.Message); - responsedata["int_response_code"] = 400; - responsedata["str_response_string"] = "false"; - return; - } - - if ((args["state"] != null) && m_aScene.m_allowScriptCrossings) - { - stateXmlStr = args["state"].AsString(); - if (stateXmlStr != "") - { - try - { - sog.SetState(stateXmlStr, regionID); - } - catch (Exception ex) - { - m_log.InfoFormat("[REST COMMS]: exception on setting state for scene object {0}", ex.Message); - - } - } - } - // This is the meaning of POST object - bool result = m_localBackend.SendCreateObject(regionhandle, sog); - - responsedata["int_response_code"] = 200; - responsedata["str_response_string"] = result.ToString(); - } - - #endregion - - #region Misc - - /// - /// Extract the param from an uri. - /// - /// Something like this: /agent/uuid/ or /agent/uuid/handle/release - /// uuid on uuid field - /// optional action - protected bool GetParams(string uri, out UUID uuid, out ulong regionHandle, out string action) - { - uuid = UUID.Zero; - action = ""; - regionHandle = 0; - - uri = uri.Trim(new char[] { '/' }); - string[] parts = uri.Split('/'); - if (parts.Length <= 1) - { - return false; - } - else - { - if (!UUID.TryParse(parts[1], out uuid)) - return false; - - if (parts.Length >= 3) - UInt64.TryParse(parts[2], out regionHandle); - if (parts.Length >= 4) - action = parts[3]; - - return true; - } - } - - #endregion Misc - - #region Hyperlinks - - protected virtual ulong GetRegionHandle(ulong handle) - { - if (m_aScene.SceneGridService is HGSceneCommunicationService) - return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.FindRegionHandle(handle); - - return handle; - } - - protected virtual bool IsHyperlink(ulong handle) - { - if (m_aScene.SceneGridService is HGSceneCommunicationService) - return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.IsHyperlinkRegion(handle); - - return false; - } - - protected virtual void SendUserInformation(RegionInfo regInfo, AgentCircuitData aCircuit) - { - try - { - //if (IsHyperlink(regInfo.RegionHandle)) - if (m_aScene.SceneGridService is HGSceneCommunicationService) - { - ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.SendUserInformation(regInfo, aCircuit); - } - } - catch // Bad cast - { } - - } - - protected virtual void AdjustUserInformation(AgentCircuitData aCircuit) - { - if (m_aScene.SceneGridService is HGSceneCommunicationService) - ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.AdjustUserInformation(aCircuit); - } - #endregion /* Hyperlinks */ - - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs deleted file mode 100644 index 9695fb8..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// AuraMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class AuraMetaEntity : PointMetaEntity - { - #region Constructors - - //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. - public AuraMetaEntity(Scene scene, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, groupPos, transparency) - { - SetAura(color, scale); - } - - public AuraMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, uuid, groupPos, transparency) - { - SetAura(color, scale); - } - - #endregion Constructors - - #region Private Methods - - private float Average(Vector3 values) - { - return (values.X + values.Y + values.Z)/3f; - } - - #endregion Private Methods - - #region Public Methods - - public void SetAura(Vector3 color, Vector3 scale) - { - SetAura(color, Average(scale) * 2.0f); - } - - public void SetAura(Vector3 color, float radius) - { - SceneObjectPart From = m_Entity.RootPart; - - //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); - float burstRadius = 0.1f; - Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; - float age = 1.5f; - float burstRate = 0.4f; - if (radius >= 8.0f) - { - //float sizeOfObject = radius / 2.0f; - burstRadius = (radius - 8.0f)/3f; - burstRate = 1.5f; - radius = 7.99f; - patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; - age = 4.0f; - } - SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); - } - - public void SetAura(SceneObjectPart From, Vector3 color, float radius, float burstRadius, float age, float burstRate, Primitive.ParticleSystem.SourcePattern patternFlags) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency - /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE - prules.PartStartScaleY = 0.5f; - prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE - prules.PartEndScaleY = 0.5f; - */ - prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE - prules.PartStartScaleY = radius; - prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE - prules.PartEndScaleY = radius; - prules.PartMaxAge = age; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - prules.Pattern = patternFlags; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT - //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS - prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - //prules.Target = To; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs deleted file mode 100644 index 3b1a45e..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// BeamMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class BeamMetaEntity : PointMetaEntity - { - #region Constructors - - public BeamMetaEntity(Scene scene, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - public BeamMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, uuid, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - #endregion Constructors - - #region Public Methods - - public void SetBeamToUUID(SceneObjectPart To, Vector3 color) - { - SceneObjectPart From = m_Entity.RootPart; - //Scale size of particles to distance objects are apart (for better visibility) - Vector3 FromPos = From.GetWorldPosition(); - Vector3 ToPos = From.GetWorldPosition(); - // UUID toUUID = To.UUID; - float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + - Math.Pow(FromPos.X-ToPos.Y, 2) + - Math.Pow(FromPos.X-ToPos.Z, 2) - ) - ); - //float rate = (float) (distance/4f); - float rate = 0.5f; - float scale = (float) (distance/128f); - float speed = (float) (2.0f - distance/128f); - - SetBeamToUUID(From, To, color, rate, scale, speed); - } - - public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, Vector3 color, float rate, float scale, float speed) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency - prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE - prules.PartStartScaleY = scale; - prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE - prules.PartEndScaleY = scale; - prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = rate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT - prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs deleted file mode 100644 index 5a86d48..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// CMController.cs -// User: bongiojp -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - /// - /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread, - /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system. - /// - public class CMController - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. - /// - private static OpenSim.Framework.BlockingQueue m_WorkQueue = new OpenSim.Framework.BlockingQueue(); - - #endregion Static Fields - - #region Fields - - //bool init = false; - int m_channel = -1; - - /// - /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. - /// - IEstateModule m_estateModule = null; - - //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) - CMModel m_model = null; - - /// - /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. - /// - Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); - State m_state = State.NONE; - Thread m_thread = null; - CMView m_view = null; - - #endregion Fields - - #region Constructors - - /// - /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. - /// - /// - /// - /// - /// - /// - /// - /// - /// The first scene to keep track of. - /// - /// - /// The simchat channel number to listen to for instructions - /// - public CMController(CMModel model, CMView view, Scene scene, int channel) - { - m_model = model; m_view = view; m_channel = channel; - RegisterNewRegion(scene); - Initialize(model, view, scene, channel); - } - - #endregion Constructors - - #region Private Methods - - //------------------------------------------------ EVENTS ----------------------------------------------------// -// private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) -// { -// } - - /// - /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned. - /// - private SceneObjectGroup GetGroupByPrim(uint localID) - { - foreach (Object currScene in m_sceneList.Values) - { - foreach (EntityBase ent in ((Scene)currScene).GetEntities()) - { - if (ent is SceneObjectGroup) - { - if (((SceneObjectGroup)ent).HasChildPrim(localID)) - return (SceneObjectGroup)ent; - } - } - } - return null; - } - - private void Initialize(CMModel model, CMView view, Scene scene, int channel) - { - lock (this) - { - m_estateModule = scene.RequestModuleInterface(); - m_thread = new Thread(MainLoop); - m_thread.Name = "Content Management"; - m_thread.IsBackground = true; - m_thread.Start(); - ThreadTracker.Add(m_thread); - m_state = State.NONE; - } - } - - /// - /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions. - /// - private void MainLoop() - { - try - { - CMModel model = m_model; CMView view = m_view; int channel = m_channel; - Work currentJob = new Work(); - while (true) - { - currentJob = m_WorkQueue.Dequeue(); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); - switch (currentJob.Type) - { - case WorkType.NONE: - break; - case WorkType.OBJECTATTRIBUTECHANGE: - ObjectAttributeChanged(model, view, currentJob.LocalId); - break; - case WorkType.PRIMITIVEADDED: - PrimitiveAdded(model, view, currentJob); - break; - case WorkType.OBJECTDUPLICATED: - ObjectDuplicated(model, view, currentJob.LocalId); - break; - case WorkType.OBJECTKILLED: - ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); - break; - case WorkType.UNDODID: - UndoDid(model, view, currentJob.UUID); - break; - case WorkType.NEWCLIENT: - NewClient(view, (IClientAPI) currentJob.Data1); - break; - case WorkType.SIMCHAT: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); - SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); - break; - default: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); - break; - } - } - } - catch (Exception e) - { - // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened - m_log.ErrorFormat( - "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", - e); - } - } - - /// - /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. - /// - private void NewClient(CMView view, IClientAPI client) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.SendMetaEntitiesToNewClient(client); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) - { - SceneObjectGroup group = null; - if ((m_state & State.SHOWING_CHANGES) > 0) - { - group = GetGroupByPrim(LocalId); - if (group != null) - { - view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura) - m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) - } - } - } - - /// - /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. - /// - private void ObjectDuplicated(CMModel model, CMView view, uint localId) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.RemoveOrUpdateDeletedEntity(group); - model.RemoveOrUpdateDeletedEntity(group); - } - } - - /// - /// Only called by the MainLoop. - /// - private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - foreach (Object scene in m_sceneList.Values) - m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); - } - } - - /// - /// Only called by the MainLoop. - /// - private void UndoDid(CMModel model, CMView view, UUID uuid) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); - if (ent != null) - view.DisplayEntity(ent); - } - } - - #endregion Private Methods - - #region Protected Methods - - protected void GroupBeingDeleted(SceneObjectGroup group) - { - m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTKILLED; - moreWork.Data1 = group.Copy(); - m_WorkQueue.Enqueue(moreWork); - } - - protected void ObjectDuplicated(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, - UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, - bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void OnNewClient(IClientAPI client) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.NEWCLIENT; - moreWork.Data1 = client; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new client"); - } - - protected void OnUnDid(IClientAPI remoteClient, UUID primId) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.UNDODID; - moreWork.UUID = primId; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] undid"); - } - - /// - /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. - /// - protected static System.Collections.Generic.List ScenesInOrderOfProximity(Hashtable sceneList, Scene scene) - { - int somethingAddedToList = 1; - System.Collections.Generic.List newList = new List(); - newList.Add(scene); - - if (!sceneList.ContainsValue(scene)) - { - foreach (Object sceneObj in sceneList) - newList.Add((Scene) sceneObj); - return newList; - } - - while (somethingAddedToList > 0) - { - somethingAddedToList = 0; - for (int i = 0; i < newList.Count; i++) - { - foreach (Object sceneObj in sceneList.Values) - { - if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (!newList.Contains((Scene)sceneObj))) - { - newList.Add((Scene)sceneObj); - somethingAddedToList++; - } - } - } - } - - foreach (Object sceneObj in sceneList.Values) - if (!newList.Contains((Scene)sceneObj)) - newList.Add((Scene)sceneObj); - - return newList; - } - - //This is stupid, the same information is contained in the first and second argument - protected void SimChatSent(Object x, OSChatMessage e) - { - m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); - m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); - Work moreWork = new Work(); - moreWork.Type = WorkType.SIMCHAT; - moreWork.Data1 = e; - m_WorkQueue.Enqueue(moreWork); - } - - /// - /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. - /// - protected void StartManaging(IClientAPI client) - { - m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); - // client.OnChatFromClient += SimChatSent; - //init = true; - - OnNewClient(client); - - m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); - client.OnUpdatePrimScale += UpdateSingleScale; - client.OnUpdatePrimGroupScale += UpdateMultipleScale; - client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition += UpdateSinglePosition; - client.OnUpdatePrimGroupRotation += UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation += UpdateSingleRotation; - client.OnAddPrim += UpdateNewParts; - client.OnObjectDuplicate += ObjectDuplicated; - client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay; - client.OnUndo += OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - } - - /// - /// - /// - protected void StopManaging(UUID clientUUID) - { - foreach (Object sceneobj in m_sceneList.Values) - { - ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); - if (presence != null) - { - IClientAPI client = presence.ControllingClient; - m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); - // client.OnChatFromViewer -= SimChatSent; - - m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); - client.OnUpdatePrimScale -= UpdateSingleScale; - client.OnUpdatePrimGroupScale -= UpdateMultipleScale; - client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; - client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; - client.OnAddPrim -= UpdateNewParts; - client.OnObjectDuplicate -= ObjectDuplicated; - client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; - client.OnUndo -= OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - return; - } - } - } - - protected void UpdateMultiplePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] pos"); - } - - protected void UpdateMultipleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateMultipleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT]scale"); - } - - protected void UpdateNewParts(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, - byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, - byte RayEndIsIntersection) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.PRIMITIVEADDED; - moreWork.UUID = ownerID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new parts"); - } - - protected void UpdateSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] move"); - } - - /// - /// - /// - protected void UpdateSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateSingleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] scale"); - } - - /// - /// Only called from within the SimChat method. - /// - protected void commit(string message, Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - string[] args = message.Split(new char[] {' '}); - - char[] logMessage = {' '}; - if (args.Length > 1) - { - logMessage = new char[message.Length - (args[0].Length)]; - message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); - } - - m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); - foreach (Scene currScene in proximitySceneList) - { - model.CommitRegion(currScene, new String(logMessage)); - view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); - } - - view.SendSimChatMessage(scene, "Successfully saved all regions."); - m_state |= State.DIRTY; - - if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES - { - view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - - //Recreate them from backend files - foreach (Scene currScene in proximitySceneList) - { - model.UpdateCMEntities(currScene); - view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); - } - - //Display new objects to users1 - view.DisplayRecentChanges(); - view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); - m_state &= ~(State.DIRTY); - m_state |= State.SHOWING_CHANGES; - } - } - - /// - /// Only called from within the SimChat method. - /// - protected void diffmode(Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF - { - view.SendSimChatMessage(scene, "Hiding all meta objects."); - view.HideAllMetaEntities(); - view.HideAllAuras(); - view.SendSimChatMessage(scene, "Diff-mode = OFF"); - - m_state &= ~State.SHOWING_CHANGES; - return; - } - else // TURN ON - { - if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) - { - view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - //Recreate them from backend files - foreach (Object currScene in m_sceneList.Values) - model.UpdateCMEntities((Scene) currScene); - } - else if ((m_state & State.DIRTY) != 0) { - view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); - foreach (Scene currScene in proximitySceneList) - model.CheckForNewEntitiesMissingAuras(currScene); - view.DisplayRecentChanges(); - - view.SendSimChatMessage(scene, "Diff-mode = ON"); - m_state |= State.SHOWING_CHANGES; - m_state &= ~State.DIRTY; - } - } - - /// - /// Only called from within the SimChat method. Hides all auras and meta entities, - /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, - /// then lets the view update the clients of the new objects. - /// - protected void rollback(Scene scene, CMModel model, CMView view) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.HideAllAuras(); - view.HideAllMetaEntities(); - } - - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - foreach (Scene currScene in proximitySceneList) - model.RollbackRegion(currScene); - - if ((m_state & State.DIRTY) != 0) - { - model.DeleteAllMetaObjects(); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayRecentChanges(); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. - /// - /// - /// A - /// - public void RegisterNewRegion(Scene scene) - { - m_sceneList.Add(scene.RegionInfo.RegionID, scene); - - m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); - m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); - - scene.EventManager.OnNewClient += StartManaging; - scene.EventManager.OnChatFromClient += SimChatSent; - scene.EventManager.OnRemovePresence += StopManaging; - // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; - } - - /// - /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. - /// - public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) - { - if (e.Channel != channel) - return; - if (e.Sender == null) - return; - - m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); - - IClientAPI client = e.Sender; - Scene scene = (Scene) e.Scene; - string message = e.Message; - string[] args = e.Message.Split(new char[] {' '}); - - ScenePresence avatar = scene.GetScenePresence(client.AgentId); - - if (!(m_estateModule.IsManager(avatar.UUID))) - { - m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); - view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); - return; - } - - switch (args[0]) - { - case "ci": - case "commit": - commit(message, scene, model, view); - break; - case "dm": - case "diff-mode": - diffmode(scene, model, view); - break; - case "rb": - case "rollback": - rollback(scene, model, view); - break; - case "help": - m_view.DisplayHelpMenu(scene); - break; - default: - view.SendSimChatMessage(scene, "Command not found: " + args[0]); - break; - } - } - - #endregion Public Methods - - #region Other - - /// - /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk. - /// - [Flags] - private enum State - { - NONE = 0, - DIRTY = 1, // The meta entities may not correctly represent the last revision. - SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. - } - - /// - /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. - /// - private struct Work - { - #region Fields - - public Object Data1; //Just space for holding data. - public Object Data2; //Just more space for holding data. - public uint LocalId; //Convenient - public WorkType Type; - public UUID UUID; //Convenient - - #endregion Fields - } - - /// - /// Identifies what the data in struct Work should be used for. - /// - private enum WorkType - { - NONE, - OBJECTATTRIBUTECHANGE, - PRIMITIVEADDED, - OBJECTDUPLICATED, - OBJECTKILLED, - UNDODID, - NEWCLIENT, - SIMCHAT - } - - #endregion Other - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs deleted file mode 100644 index cfd5cde..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// CMEntityCollection.cs created with MonoDevelop -// User: bongiojp at 10:09 AM 7/7/2008 -// -// Creates, Deletes, Stores ContentManagementEntities -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class CMEntityCollection - { - #region Fields - - // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or - // old versions of deleted SceneObjectGroups will be stored in this hash table. - // The UUID keys are from the SceneObjectGroup RootPart UUIDs - protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //UUID to ContentManagementEntity - - // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable - // The UUID keys are from the SceneObjectPart that they are supposed to be on. - protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //UUID to AuraMetaEntity - - #endregion Fields - - #region Constructors - - public CMEntityCollection() - { - } - - #endregion Constructors - - #region Public Properties - - public Hashtable Auras - { - get {return m_NewlyCreatedEntityAura; } - } - - public Hashtable Entities - { - get { return m_CMEntityHash; } - } - - #endregion Public Properties - - #region Public Methods - - public bool AddAura(ContentManagementEntity aura) - { - if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) - return false; - m_NewlyCreatedEntityAura.Add(aura.UUID, aura); - return true; - } - - public bool AddEntity(ContentManagementEntity ent) - { - if (m_CMEntityHash.ContainsKey(ent.UUID)) - return false; - m_CMEntityHash.Add(ent.UUID, ent); - return true; - } - - // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash - public System.Collections.ArrayList CheckForMissingEntities(System.Collections.Generic.List currList) - { - System.Collections.ArrayList missingList = new System.Collections.ArrayList(); - SceneObjectGroup temp = null; - foreach (EntityBase currObj in currList) - { - if (!(currObj is SceneObjectGroup)) - continue; - temp = (SceneObjectGroup) currObj; - - if (m_CMEntityHash.ContainsKey(temp.UUID)) - { - foreach (SceneObjectPart part in temp.Children.Values) - if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) - missingList.Add(part); - } - else //Entire group is missing from revision. (and is a new part in region) - { - foreach (SceneObjectPart part in temp.Children.Values) - missingList.Add(part); - } - } - return missingList; - } - - public void ClearAll() - { - m_CMEntityHash.Clear(); - m_NewlyCreatedEntityAura.Clear(); - } - - // Old uuid and new sceneobjectgroup - public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) - { - AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0,254,0), - part.Scale - ); - m_NewlyCreatedEntityAura.Add(part.UUID, ent); - return ent; - } - - // Old uuid and new sceneobjectgroup - public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) - { - ContentManagementEntity ent = new ContentManagementEntity(group, false); - m_CMEntityHash.Add(group.UUID, ent); - return ent; - } - - public ContentManagementEntity CreateNewEntity(String xml, Scene scene) - { - ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); - if (ent == null) - return null; - m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); - return ent; - } - - public bool RemoveEntity(UUID uuid) - { - if (!m_CMEntityHash.ContainsKey(uuid)) - return false; - m_CMEntityHash.Remove(uuid); - return true; - } - - public bool RemoveNewlyCreatedEntityAura(UUID uuid) - { - if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) - return false; - m_NewlyCreatedEntityAura.Remove(uuid); - return true; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs deleted file mode 100644 index 6399608..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// CMModel.cs -// User: bongiojp -// -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class CMModel - { - #region Static Fields - - static float TimeToUpdate = 0; - static float TimeToConvertXml = 0; - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - /// - /// The class that contains all auras and metaentities used in the CMS. - /// - CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); - IContentDatabase m_database = null; - - #endregion Fields - - #region Constructors - - public CMModel() - { - } - - #endregion Constructors - - #region Public Properties - - public CMEntityCollection MetaEntityCollection - { - get { return m_MetaEntityCollection; } - } - - #endregion Public Properties - - #region Public Methods - - /// - /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity - /// it is a new part that must have a green aura (for diff mode). - /// Returns list of ContentManagementEntities - /// - public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) - { - ArrayList missingList = null; - ArrayList newList = new ArrayList(); - - m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); - - //Check if the current scene has groups not included in the current list of MetaEntities - //If so, then the current scene's parts that are new should be marked green. - missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); - - foreach (Object missingPart in missingList) - { - if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) - continue; - newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); - } - m_log.Info("Number of missing objects found: " + newList.Count); - return newList; - } - - /// - /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. - /// - public void CommitRegion(Scene scene, String logMessage) - { - m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); - m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); - m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName ); - } - - public void DeleteAllMetaObjects() - { - m_MetaEntityCollection.ClearAll(); - } - - public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid) - { - ContentManagementEntity ent = GetMetaGroupByPrim(uuid); - return ent; - } - - //-------------------------------- HELPERS --------------------------------------------------------------------// - public ContentManagementEntity GetMetaGroupByPrim(UUID uuid) - { - foreach (Object ent in m_MetaEntityCollection.Entities.Values) - { - if (((ContentManagementEntity)ent).HasChildPrim(uuid)) - return (ContentManagementEntity)ent; - } - return null; - } - - public void Initialise(string database) - { - if (database == "FileSystemDatabase") - m_database = new FileSystemDatabase(); - else if (database == "GitDatabase") - m_database = new GitDatabase(); - } - - public void InitialiseDatabase(Scene scene, string dir) - { - m_database.Initialise(scene, dir); - } - - /// - /// Should be called just once to finish initializing the database. - /// - public void PostInitialise() - { - m_database.PostInitialise(); - } - - /// - /// Removes the green aura when an a new scene object group is deleted. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with new parts not revisioned that have been deleted. - foreach (SceneObjectPart part in group.Children.Values) - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); - } - - /// - /// Retrieves the latest revision of a region in xml form, - /// converts it to scene object groups and scene presences, - /// swaps the current scene's entity list with the revision's list. - /// Note: Since deleted objects while - /// - public void RollbackRegion(Scene scene) - { - System.Collections.ArrayList xmllist = null; - SceneObjectGroup temp = null; - System.Collections.Hashtable deleteListUUIDs = new Hashtable(); -// Dictionary SearchList = new Dictionary(); - Dictionary ReplacementList = new Dictionary(); - int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); -// EntityBase[] searchArray; - - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); - if (xmllist == null) - { - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); - return; - } - - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); - m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); - m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); - - m_log.ErrorFormat("[CMMODEL]: 1"); - - foreach (string xml in xmllist) - { - try{ - temp = new SceneObjectGroup(xml); - temp.SetScene(scene); - foreach (SceneObjectPart part in temp.Children.Values) - part.RegionHandle = scene.RegionInfo.RegionHandle; - ReplacementList.Add(temp.UUID, (EntityBase)temp); - } - catch(Exception e) - { - m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e); - } - } - - //If in scene but not in revision and not a client, remove them - while (true) - { - try - { - foreach (EntityBase entity in scene.GetEntities()) - { - if (entity == null) - continue; - - if (entity is ScenePresence) - { - ReplacementList.Add(entity.UUID, entity); - continue; - } - else //if (!ReplacementList.ContainsKey(entity.UUID)) - deleteListUUIDs.Add(entity.UUID, 0); - } - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: " + e); - deleteListUUIDs.Clear(); - ReplacementList.Clear(); - continue; - } - break; - } - - foreach (UUID uuid in deleteListUUIDs.Keys) - { - try - { - // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. - ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); - scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); - scene.SendKillObject(scene.Entities[uuid].LocalId); - scene.m_sceneGraph.DeleteSceneObject(uuid, false); - ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup(false); - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); - } - } - - lock (scene) - { - scene.Entities.Clear(); - - foreach (KeyValuePair kvp in ReplacementList) - { - scene.Entities.Add(kvp.Value); - } - } - - foreach (EntityBase ent in ReplacementList.Values) - { - try - { - if (!(ent is SceneObjectGroup)) - continue; - - if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0) - ((SceneObjectGroup)ent).ApplyPhysics(true); - ((SceneObjectGroup)ent).AttachToBackup(); - ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. - ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e); - } - } - m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); - scene.Backup(); - } - - /// - /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences - /// and display the differences to clients. - /// - public void UpdateCMEntities(Scene scene) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - System.Collections.ArrayList xmllist = null; - m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID); - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID); - m_log.Info("[FSDB]: got list"); - if (xmllist == null) - return; - - Stopwatch y = new Stopwatch(); - y.Start(); - foreach (string xml in xmllist) - m_MetaEntityCollection.CreateNewEntity(xml, scene); - y.Stop(); - TimeToConvertXml += y.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); - - m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); - CheckForNewEntitiesMissingAuras(scene); - - x.Stop(); - TimeToUpdate += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); - } - - /// - /// Detects if a scene object group from the scene list has moved or changed scale. The green aura - /// that surrounds the object is then moved or scaled with the group. - /// - public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) - { - System.Collections.ArrayList auraList = new System.Collections.ArrayList(); - if (group == null) - return null; - foreach (SceneObjectPart part in group.Children.Values) - { - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - { - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale); - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); - auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); - } - } - return auraList; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs deleted file mode 100644 index e5c9bb3..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// CMView.cs created with MonoDevelop -// User: bongiojp at 11:57 AM 7/3/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class CMView - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - CMModel m_model = null; - - #endregion Fields - - #region Constructors - - public CMView() - { - } - - #endregion Constructors - - #region Public Methods - - // Auras To - public void DisplayAuras(CMEntityCollection auraCollection) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - - // Auras To Client - public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdate(client); - } - - // Auras from List To ALL - public void DisplayAuras(ArrayList list) - { - foreach (Object ent in list) - { - m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - } - - // Entities to ALL - public void DisplayEntities(CMEntityCollection entityCollection) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entities to Client - public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdate(client); - } - - // Entities from List to ALL - public void DisplayEntities(ArrayList list) - { - foreach (Object ent in list) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entity to ALL - public void DisplayEntity(ContentManagementEntity ent) - { - ent.SendFullDiffUpdateToAll(); - } - - public void DisplayHelpMenu(Scene scene) - { - string menu = "Menu:\n"; - menu += "commit (ci) - saves current state of the region to a database on the server\n"; - menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n"; - SendSimChatMessage(scene, menu); - } - - public void DisplayMetaEntity(UUID uuid) - { - ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); - if (group != null) - group.SendFullDiffUpdateToAll(); - } - - /// - /// update all clients of red/green/blue auras and meta entities that the model knows about. - /// - public void DisplayRecentChanges() - { - m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); - DisplayEntities(m_model.MetaEntityCollection); - DisplayAuras(m_model.MetaEntityCollection); - } - - public void Hide(ContentManagementEntity ent) - { - ent.HideFromAll(); - } - - public void HideAllAuras() - { - foreach (Object obj in m_model.MetaEntityCollection.Auras.Values) - ((MetaEntity)obj).HideFromAll(); - } - - public void HideAllMetaEntities() - { - foreach (Object obj in m_model.MetaEntityCollection.Entities.Values) - ((ContentManagementEntity)obj).HideFromAll(); - } - - public void Initialise(CMModel model) - { - m_model = model; - } - - /// - /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. - /// If it's a new scene object, any green aura attached to it is deleted. - /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will - /// figure out that there should be a red aura and not a blue aura/beam. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with revisioned parts that have been deleted. - if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) - ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); - - // Deal with new parts not revisioned that have been deleted. - foreach (SceneObjectPart part in group.Children.Values) - if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) - ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); - } - - public void SendMetaEntitiesToNewClient(IClientAPI client) - { - } - - public void SendSimChatMessage(Scene scene, string message) - { - scene.SimChat(Utils.StringToBytes(message), - ChatTypeEnum.Broadcast, 0, new Vector3(0,0,0), "Content Manager", UUID.Zero, false); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs deleted file mode 100644 index 2ea5ebc..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// ContentManagementEntity.cs -// User: bongiojp -// -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class ContentManagementEntity : MetaEntity - { - #region Static Fields - -// static float TimeToDiff = 0; -// static float TimeToCreateEntities = 0; - - #endregion Static Fields - - #region Fields - - protected Dictionary m_AuraEntities = new Dictionary(); - protected Dictionary m_BeamEntities = new Dictionary(); - - // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. - // This can come in handy. - protected SceneObjectGroup m_UnchangedEntity = null; - - /// - /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. - /// - bool DiffersFromSceneGroup = false; - - #endregion Fields - - #region Constructors - - public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) - : base(Unchanged, false) - { - m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false); - } - - public ContentManagementEntity(string objectXML, Scene scene, bool physics) - : base(objectXML, scene, false) - { - m_UnchangedEntity = new SceneObjectGroup(objectXML); - } - - #endregion Constructors - - #region Public Properties - - public SceneObjectGroup UnchangedEntity - { - get { return m_UnchangedEntity; } - } - - #endregion Public Properties - - #region Private Methods - - /// - /// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid. - /// - private bool ContainsKey(List list, UUID uuid) - { - foreach (EntityBase part in list) - if (part.UUID == uuid) - return true; - return false; - } - - private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List list, UUID uuid) - { - foreach (EntityBase ent in list) - { - if (ent is SceneObjectGroup) - if (ent.UUID == uuid) - return (SceneObjectGroup)ent; - } - return null; - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately. - /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. - /// - public void FindDifferences() - { - System.Collections.Generic.List sceneEntityList = m_Entity.Scene.GetEntities(); - DiffersFromSceneGroup = false; - // if group is not contained in scene's list - if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) - { - // if scene list no longer contains this part, display translucent part and mark with red aura - if (!ContainsKey(sceneEntityList, part.UUID)) - { - // if already displaying a red aura over part, make sure its red - if (m_AuraEntities.ContainsKey(part.UUID)) - { - m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale); - } - else - { - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254,0,0), - part.Scale - ); - m_AuraEntities.Add(part.UUID, auraGroup); - } - SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); - SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); - } - // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id - } - - // a deleted part has no where to point a beam particle system, - // if a metapart had a particle system (maybe it represented a moved part) remove it - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - - DiffersFromSceneGroup = true; - } - // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately - else - { - MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); - } - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. - /// - public bool HasChildPrim(UUID uuid) - { - if (m_UnchangedEntity.Children.ContainsKey(uuid)) - return true; - return false; - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. - /// - public bool HasChildPrim(uint localID) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) - if (part.LocalId == localID) - return true; - return false; - } - - public override void Hide(IClientAPI client) - { - base.Hide(client); - foreach (MetaEntity group in m_AuraEntities.Values) - group.Hide(client); - foreach (MetaEntity group in m_BeamEntities.Values) - group.Hide(client); - } - - public override void HideFromAll() - { - base.HideFromAll(); - foreach (MetaEntity group in m_AuraEntities.Values) - group.HideFromAll(); - foreach (MetaEntity group in m_BeamEntities.Values) - group.HideFromAll(); - } - - /// - /// Returns true if there was a change between meta entity and the entity group, false otherwise. - /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). - /// - public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) - { - SceneObjectPart sceneEntityPart; - SceneObjectPart metaEntityPart; - Diff differences; - bool changed = false; - - // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user - // had originally saved. - // m_Entity will NOT necessarily be the same entity as the user had saved. - foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) - { - //This is the part that we use to show changes. - metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); - if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) - { - sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; - differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); - if (differences != Diff.NONE) - metaEntityPart.Text = "CHANGE: " + differences.ToString(); - if (differences != 0) - { - // Root Part that has been modified - if ((differences&Diff.POSITION) > 0) - { - // If the position of any part has changed, make sure the RootPart of the - // meta entity is pointing with a beam particle system - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, - m_UnchangedEntity.RootPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - sceneEntityPart, - new Vector3(0,0,254) - ); - m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); - } - - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0,0,254), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - else // no differences between scene part and meta part - { - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - SetPartTransparency(metaEntityPart, MetaEntity.NONE); - } - } - else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. - { - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254,0,0), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - } - return changed; - } - - public void SendFullAuraUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullAuraUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullBeamUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullBeamUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullDiffUpdate(IClientAPI client) - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdate(client); - SendFullAuraUpdate(client); - SendFullBeamUpdate(client); - } - } - - public void SendFullDiffUpdateToAll() - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdateToAll(); - SendFullAuraUpdateToAll(); - SendFullBeamUpdateToAll(); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs deleted file mode 100644 index 417cbce..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// ContentManagementModule.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class ContentManagementModule : IRegionModule - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - bool initialised = false; - CMController m_control = null; - bool m_enabled = false; - CMModel m_model = null; - bool m_posted = false; - CMView m_view = null; - - #endregion Fields - - #region Public Properties - - public bool IsSharedModule - { - get { return true; } - } - - public string Name - { - get { return "ContentManagementModule"; } - } - - #endregion Public Properties - - #region Public Methods - - public void Close() - { - } - - public void Initialise(Scene scene, IConfigSource source) - { - string databaseDir = "./"; - string database = "FileSystemDatabase"; - int channel = 345; - try - { - if (source.Configs["CMS"] == null) - return; - - m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); - databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); - database = source.Configs["CMS"].GetString("database", database); - channel = source.Configs["CMS"].GetInt("channel", channel); - - if (database != "FileSystemDatabase" && database != "GitDatabase") - { - m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); - m_enabled = false; - } - } - catch (Exception e) - { - m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); - m_enabled = false; - } - - if (!m_enabled) - { - m_log.Info("[Content Management]: Content Management System is not Enabled."); - return; - } - - lock (this) - { - if (!initialised) //only init once - { - m_view = new CMView(); - m_model = new CMModel(); - m_control = new CMController(m_model, m_view, scene, channel); - m_model.Initialise(database); - m_view.Initialise(m_model); - - initialised = true; - m_model.InitialiseDatabase(scene, databaseDir); - } - else - { - m_model.InitialiseDatabase(scene, databaseDir); - m_control.RegisterNewRegion(scene); - } - } - } - - public void PostInitialise() - { - if (! m_enabled) - return; - - lock (this) - { - if (!m_posted) //only post once - { - m_model.PostInitialise(); - m_posted = true; - } - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs deleted file mode 100644 index 65db153..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// FileSystemDatabase.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Serialiser; -using OpenSim.Region.Environment.Modules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class FileSystemDatabase : IContentDatabase - { - #region Static Fields - - public static float TimeToDownload = 0; - public static float TimeToSave = 0; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - private string m_repodir = null; - private Dictionary m_scenes = new Dictionary(); - private Dictionary m_serialiser = new Dictionary(); - - #endregion Fields - - #region Constructors - - public FileSystemDatabase() - { - } - - #endregion Constructors - - #region Private Methods - - // called by postinitialise - private void CreateDirectory() - { - string scenedir; - if (!Directory.Exists(m_repodir)) - Directory.CreateDirectory(m_repodir); - - foreach (UUID region in m_scenes.Keys) - { - scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - } - } - - // called by postinitialise - private void SetupSerialiser() - { - if (m_serialiser.Count == 0) - { - foreach (UUID region in m_scenes.Keys) - { - m_serialiser.Add(region, m_scenes[region].RequestModuleInterface()); - } - } - } - - #endregion Private Methods - - #region Public Methods - - public int GetMostRecentRevision(UUID regionid) - { - return NumOfRegionRev(regionid); - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream( filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream( filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - System.Collections.ArrayList objectList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - //int primCount = 0; - //SceneObjectGroup obj = null; - - if (File.Exists(filename)) - { - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - objectList.Add(aPrimNode.OuterXml); - } - return objectList; - } - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - int revision = NumOfRegionRev(regionid); - m_log.Info("[FSDB]: found revisions:" + revision); - System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - - m_log.Info("[FSDB]: Checking if " + filename + " exists."); - if (File.Exists(filename)) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - xmlList.Add(aPrimNode.OuterXml); - } - - x.Stop(); - TimeToDownload += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); - - return xmlList; - } - return null; - } - - public void Initialise(Scene scene, string dir) - { - lock (this) - { - if (m_repodir == null) - m_repodir = dir; - } - lock (m_scenes) - m_scenes.Add(scene.RegionInfo.RegionID, scene); - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID regionid) - { - SortedDictionary revisionDict = new SortedDictionary(); - - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - string[] directories = Directory.GetDirectories(scenedir); - - FileStream fs = null; - StreamReader sr = null; - String logMessage = ""; - String logLocation = ""; - foreach (string revisionDir in directories) - { - try - { - logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; - fs = new FileStream( logLocation, FileMode.Open); - sr = new StreamReader(fs); - logMessage = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - revisionDict.Add(revisionDir, logMessage); - } - catch (Exception) - { - } - } - - return revisionDict; - } - - public int NumOfRegionRev(UUID regionid) - { - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - m_log.Info("[FSDB]: Reading scene dir: " + scenedir); - string[] directories = Directory.GetDirectories(scenedir); - return directories.Length; - } - - // Run once and only once. - public void PostInitialise() - { - SetupSerialiser(); - - m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); - CreateDirectory(); - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - m_log.Info("[FSDB]: ..............................."); - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - - int newRevisionNum = GetMostRecentRevision(regionid)+1; - string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); - if (!Directory.Exists(revisiondir)) - Directory.CreateDirectory(revisiondir); - - try { - Stopwatch x = new Stopwatch(); - x.Start(); - if (m_scenes.ContainsKey(regionid)) - { - m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); - } - x.Stop(); - TimeToSave += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); - return; - } - - try { - // Finish by writing log message. - FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); - StreamWriter sw = new StreamWriter(file); - sw.Write(logMessage); - sw.Close(); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); - return; - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs deleted file mode 100644 index 4209dab..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// GitDatabase.cs -// -// -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Serialiser; -using OpenSim.Region.Environment.Modules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - /// - /// Just a stub :-( - /// - public class GitDatabase : IContentDatabase - { - #region Constructors - - public GitDatabase() - { - } - - #endregion Constructors - - #region Public Methods - - public SceneObjectGroup GetMostRecentObjectRevision(UUID id) - { - return null; - } - - public int GetMostRecentRevision(UUID regionid) - { - return 0; - } - - public SceneObjectGroup GetObjectRevision(UUID id, int revision) - { - return null; - } - - public System.Collections.ArrayList GetObjectsFromRegion(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid, int revision) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - return null; - } - - public bool InRepository(UUID id) - { - return false; - } - - public void Initialise(Scene scene, String dir) - { - } - - public System.Collections.Generic.SortedDictionary ListOfObjectRevisions(UUID id) - { - return null; - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id) - { - return null; - } - - public int NumOfObjectRev(UUID id) - { - return 0; - } - - public int NumOfRegionRev(UUID regionid) - { - return 0; - } - - public void PostInitialise() - { - } - - public void SaveObject(SceneObjectGroup entity) - { - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs deleted file mode 100644 index 79dc86e..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// IContentDatabase.cs -// User: bongiojp -// -// -// - -#endregion Header - -using System; -using OpenMetaverse; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public interface IContentDatabase - { - #region Methods - - /// - /// Returns the most recent revision number of a region. - /// - int GetMostRecentRevision(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid, int revision); - - /// - /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. - /// - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid); - - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision); - - /// - /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. - /// Initialise should be called one for each region to be contained in the database. The directory should be the full path - /// to the repository and will only be defined once, regardless of how many times the method is called. - /// - void Initialise(Scene scene, String dir); - - /// - /// Returns a list of the revision numbers and corresponding log messages for a given region. - /// - System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id); - - /// - /// Returns the total number of revisions saved for a specific region. - /// - int NumOfRegionRev(UUID regionid); - - /// - /// Should be called once after Initialise has been called. - /// - void PostInitialise(); - - /// - /// Saves the Region terrain map and objects within the region as xml to the database. - /// - void SaveRegion(UUID regionid, string regionName, string logMessage); - - #endregion Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs deleted file mode 100644 index c8f8c2f..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// MetaEntity.cs -// User: bongiojp -// -// TODO: -// Create a physics manager to the meta object if there isn't one or the object knows of no scene but the user wants physics enabled. - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class MetaEntity - { - #region Constants - - public const float INVISIBLE = .95f; - - // Settings for transparency of metaentity - public const float NONE = 0f; - public const float TRANSLUCENT = .5f; - - #endregion Constants - - #region Static Fields - - protected static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. - protected uint m_metaLocalid; - - #endregion Fields - - #region Constructors - - public MetaEntity() - { - } - - /// - /// Makes a new meta entity by copying the given scene object group. - /// The physics boolean is just a stub right now. - /// - public MetaEntity(SceneObjectGroup orig, bool physics) - { - m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false); - Initialize(physics); - } - - /// - /// Takes an XML description of a scene object group and converts it to a meta entity. - /// - public MetaEntity(string objectXML, Scene scene, bool physics) - { - m_Entity = new SceneObjectGroup(objectXML); - m_Entity.SetScene(scene); - Initialize(physics); - } - - #endregion Constructors - - #region Public Properties - - public Dictionary Children - { - get { return m_Entity.Children; } - set { m_Entity.Children = value; } - } - - public uint LocalId - { - get { return m_Entity.LocalId; } - set { m_Entity.LocalId = value; } - } - - public SceneObjectGroup ObjectGroup - { - get { return m_Entity; } - } - - public int PrimCount - { - get { return m_Entity.PrimCount; } - } - - public SceneObjectPart RootPart - { - get { return m_Entity.RootPart; } - } - - public Scene Scene - { - get { return m_Entity.Scene; } - } - - public UUID UUID - { - get { return m_Entity.UUID; } - set { m_Entity.UUID = value; } - } - - #endregion Public Properties - - #region Protected Methods - - // The metaentity objectgroup must have unique localids as well as unique uuids. - // localids are used by the client to refer to parts. - // uuids are sent to the client and back to the server to identify parts on the server side. - /// - /// Changes localids and uuids of m_Entity. - /// - protected void Initialize(bool physics) - { - //make new uuids - Dictionary parts = new Dictionary(); - foreach (SceneObjectPart part in m_Entity.Children.Values) - { - part.ResetIDs(part.LinkNum); - parts.Add(part.UUID, part); - } - - //finalize - m_Entity.RootPart.PhysActor = null; - m_Entity.Children = parts; - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Hides the metaentity from a single client. - /// - public virtual void Hide(IClientAPI client) - { - //This deletes the group without removing from any databases. - //This is important because we are not IN any database. - //m_Entity.FakeDeleteGroup(); - foreach (SceneObjectPart part in m_Entity.Children.Values) - client.SendKillObject(m_Entity.RegionHandle, part.LocalId); - } - - /// - /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. - /// - public virtual void HideFromAll() - { - foreach (SceneObjectPart part in m_Entity.Children.Values) - m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } - ); - } - - public void SendFullUpdate(IClientAPI client) - { - // Not sure what clientFlags should be but 0 seems to work - SendFullUpdate(client, 0); - } - - public void SendFullUpdate(IClientAPI client, uint clientFlags) - { - m_Entity.SendFullUpdateToClient(client); - } - - public void SendFullUpdateToAll() - { - m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) - { m_Entity.SendFullUpdateToClient(controller); } - ); - } - - /// - /// Makes a single SceneObjectPart see through. - /// - /// - /// A - /// The part to make see through - /// - /// - /// A - /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. - /// - public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) - { - Primitive.TextureEntry tex = null; - Color4 texcolor; - try - { - tex = part.Shape.Textures; - texcolor = new Color4(); - } - catch(Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); - return; - } - - for (uint i = 0; i < tex.FaceTextures.Length; i++) - { - try { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = transparencyAmount; - tex.FaceTextures[i].RGBA = texcolor; - } - } - catch (Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); - continue; - } - } - try { - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = transparencyAmount; - tex.DefaultTexture.RGBA = texcolor; - part.Shape.TextureEntry = tex.ToBytes(); - } - catch (Exception) - { - //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs deleted file mode 100644 index d6ba92f..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// PointMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class PointMetaEntity : MetaEntity - { - #region Constructors - - public PointMetaEntity(Scene scene, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, UUID.Random(), groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - public PointMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, uuid, groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - #endregion Constructors - - #region Private Methods - - private void CreatePointEntity(Scene scene, UUID uuid, Vector3 groupPos) - { - SceneObjectGroup x = new SceneObjectGroup(); - SceneObjectPart y = new SceneObjectPart(); - - //Initialize part - y.Name = "Very Small Point"; - y.RegionHandle = scene.RegionInfo.RegionHandle; - y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; - y.OwnerID = UUID.Zero; - y.CreatorID = UUID.Zero; - y.LastOwnerID = UUID.Zero; - y.UUID = uuid; - - y.Shape = PrimitiveBaseShape.CreateBox(); - y.Scale = new Vector3(0.01f,0.01f,0.01f); - y.LastOwnerID = UUID.Zero; - y.GroupPosition = groupPos; - y.OffsetPosition = new Vector3(0, 0, 0); - y.RotationOffset = new Quaternion(0,0,0,0); - y.Velocity = new Vector3(0, 0, 0); - y.RotationalVelocity = new Vector3(0, 0, 0); - y.AngularVelocity = new Vector3(0, 0, 0); - y.Acceleration = new Vector3(0, 0, 0); - - y.Flags = 0; - y.TrimPermissions(); - - //Initialize group and add part as root part - x.SetScene(scene); - x.SetRootPart(y); - x.RegionHandle = scene.RegionInfo.RegionHandle; - x.SetScene(scene); - - m_Entity = x; - } - - #endregion Private Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/README b/OpenSim/Region/Environment/Modules/ContentManagementSystem/README deleted file mode 100644 index 1a69fef..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/README +++ /dev/null @@ -1,52 +0,0 @@ -This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a -reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/ -directory. - -To compile: nant -To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory. - - --------------------------------------------------------------------------------------------------------------------- -To build the libgit.so file: - -#Download GIT git repository -$ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git -$ cd git - -#Compile GIT -#Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC) -$ autoconf -$ ./configure -$ CFLAGS="-g -O2 -Wall -c -fPIC" make - -#Copy necessary object files (and some not so necessary) to their own directory for shared object file creation -$ mkdir ../libgit-objects -$ cp builtin*.o ../libgit-objects -$ cp xdiff/*.o ../libgit-objects -$ cp libgit.a ../libgit-objects - -#Remove the main symbol from any object files (like git.o) -$ cd ../libgit-objects -$ strip -N main *.o - -#Uncompress the plumbing objects from archive created by git -$ ar x libgit.a - -#Create shared object file from all objects (including the zlib library) -$ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o - - -#You can also just copy the following commands into a file and run as a script inside the git directory - -make clean -autoconf -./configure -CFLAGS="-g -O2 -Wall -c -fPIC" make -mkdir libgit-objects -cp builtin*.o libgit-objects -cp xdiff/*.o libgit-objects -cp libgit.a libgit-objects -cd libgit-objects -strip -N main *.o -ar x libgit.a -ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs deleted file mode 100644 index 225a682..0000000 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// SceneObjectGroupDiff.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - #region Enumerations - - [Flags] - public enum Diff - { - NONE = 0, - FACECOLOR = 1, - SHAPE = 1<<1, - MATERIAL = 1<<2, - TEXTURE = 1<<3, - SCALE = 1<<4, - POSITION = 1<<5, - OFFSETPOSITION = 1<<6, - ROTATIONOFFSET = 1<<7, - ROTATIONALVELOCITY = 1<<8, - ACCELERATION = 1<<9, - ANGULARVELOCITY = 1<<10, - VELOCITY = 1<<11, - OBJECTOWNER = 1<<12, - PERMISSIONS = 1<<13, - DESCRIPTION = 1<<14, - NAME = 1<<15, - SCRIPT = 1<<16, - CLICKACTION = 1<<17, - PARTICLESYSTEM = 1<<18, - GLOW = 1<<19, - SALEPRICE = 1<<20, - SITNAME = 1<<21, - SITTARGETORIENTATION = 1<<22, - SITTARGETPOSITION = 1<<23, - TEXT = 1<<24, - TOUCHNAME = 1<<25 - } - - #endregion Enumerations - - public static class Difference - { - #region Static Fields - - static float TimeToDiff = 0; -// private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Private Methods - - private static bool AreQuaternionsEquivalent(Quaternion first, Quaternion second) - { - Vector3 firstVector = llRot2Euler(first); - Vector3 secondVector = llRot2Euler(second); - return AreVectorsEquivalent(firstVector, secondVector); - } - - private static bool AreVectorsEquivalent(Vector3 first, Vector3 second) - { - if (TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) - && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) - && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) - ) - return true; - else - return false; - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - private static double NormalizeAngle(double angle) - { - angle = angle % (Math.PI * 2); - if (angle < 0) angle = angle + Math.PI * 2; - return angle; - } - - private static int TruncateSignificant(float num, int digits) - { - return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); - // return (int) ((num * (10*digits))/10*digits); - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - // Also changed the original function from LSL_Types to LL types - private static Vector3 llRot2Euler(Quaternion r) - { - Quaternion t = new Quaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W); - double m = (t.X + t.Y + t.Z + t.W); - if (m == 0) return new Vector3(); - double n = 2 * (r.Y * r.W + r.X * r.Z); - double p = m * m - n * n; - if (p > 0) - return new Vector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))), - (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), - (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W)))); - else if (n > 0) - return new Vector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - else - return new Vector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts - /// and returns a Diff bitmask which details what the differences are. - /// - public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - Diff result = 0; - - // VECTOR COMPARISONS - if (!AreVectorsEquivalent(first.Acceleration, second.Acceleration)) - result |= Diff.ACCELERATION; - if (!AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) - result |= Diff.POSITION; - if (!AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) - result |= Diff.ANGULARVELOCITY; - if (!AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) - result |= Diff.OFFSETPOSITION; - if (!AreVectorsEquivalent(first.RotationalVelocity, second.RotationalVelocity)) - result |= Diff.ROTATIONALVELOCITY; - if (!AreVectorsEquivalent(first.Scale, second.Scale)) - result |= Diff.SCALE; - if (!AreVectorsEquivalent(first.Velocity, second.Velocity)) - result |= Diff.VELOCITY; - - - // QUATERNION COMPARISONS - if (!AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) - result |= Diff.ROTATIONOFFSET; - - - // MISC COMPARISONS (UUID, Byte) - if (first.ClickAction != second.ClickAction) - result |= Diff.CLICKACTION; - if (first.ObjectOwner != second.ObjectOwner) - result |= Diff.OBJECTOWNER; - - - // STRING COMPARISONS - if (first.Description != second.Description) - result |= Diff.DESCRIPTION; - if (first.Material != second.Material) - result |= Diff.MATERIAL; - if (first.Name != second.Name) - result |= Diff.NAME; - if (first.SitName != second.SitName) - result |= Diff.SITNAME; - if (first.Text != second.Text) - result |= Diff.TEXT; - if (first.TouchName != second.TouchName) - result |= Diff.TOUCHNAME; - - x.Stop(); - TimeToDiff += x.ElapsedMilliseconds; - //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); - - return result; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs deleted file mode 100644 index fb30321..0000000 --- a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueGetModule.cs +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Threading; -using System.Xml; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenMetaverse.StructuredData; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Communications.Capabilities; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -using OSD = OpenMetaverse.StructuredData.OSD; -using OSDMap = OpenMetaverse.StructuredData.OSDMap; -using OSDArray = OpenMetaverse.StructuredData.OSDArray; -using Caps = OpenSim.Framework.Communications.Capabilities.Caps; -using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue; - -namespace OpenSim.Region.Environment.Modules.Framework.EventQueue -{ - public struct QueueItem - { - public int id; - public OSDMap body; - } - - public class EventQueueGetModule : IEventQueue, IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Scene m_scene = null; - private IConfigSource m_gConfig; - bool enabledYN = false; - - private Dictionary m_ids = new Dictionary(); - - private Dictionary queues = new Dictionary(); - private Dictionary m_QueueUUIDAvatarMapping = new Dictionary(); - private Dictionary m_AvatarQueueUUIDMapping = new Dictionary(); - - #region IRegionModule methods - public void Initialise(Scene scene, IConfigSource config) - { - m_gConfig = config; - - IConfig startupConfig = m_gConfig.Configs["Startup"]; - - ReadConfigAndPopulate(scene, startupConfig, "Startup"); - - if (enabledYN) - { - m_scene = scene; - scene.RegisterModuleInterface(this); - - // Register fallback handler - // Why does EQG Fail on region crossings! - - //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); - - scene.EventManager.OnNewClient += OnNewClient; - - // TODO: Leaving these open, or closing them when we - // become a child is incorrect. It messes up TP in a big - // way. CAPS/EQ need to be active as long as the UDP - // circuit is there. - - scene.EventManager.OnClientClosed += ClientClosed; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; - scene.EventManager.OnRegisterCaps += OnRegisterCaps; - } - else - { - m_gConfig = null; - } - - } - - private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p) - { - enabledYN = startupConfig.GetBoolean("EventQueue", true); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "EventQueueGetModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - #endregion - - /// - /// Always returns a valid queue - /// - /// - /// - private BlockingLLSDQueue TryGetQueue(UUID agentId) - { - lock (queues) - { - if (!queues.ContainsKey(agentId)) - { - m_log.DebugFormat( - "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}", - agentId, m_scene.RegionInfo.RegionName); - - queues[agentId] = new BlockingLLSDQueue(); - } - - return queues[agentId]; - } - } - - /// - /// May return a null queue - /// - /// - /// - private BlockingLLSDQueue GetQueue(UUID agentId) - { - lock (queues) - { - if (queues.ContainsKey(agentId)) - { - return queues[agentId]; - } - else - return null; - } - } - - #region IEventQueue Members - - public bool Enqueue(OSD ev, UUID avatarID) - { - //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName); - try - { - BlockingLLSDQueue queue = GetQueue(avatarID); - if (queue != null) - queue.Enqueue(ev); - } - catch(NullReferenceException e) - { - m_log.Error("[EVENTQUEUE] Caught exception: " + e); - return false; - } - - return true; - } - - #endregion - - private void OnNewClient(IClientAPI client) - { - //client.OnLogout += ClientClosed; - } - -// private void ClientClosed(IClientAPI client) -// { -// ClientClosed(client.AgentId); -// } - - private void ClientClosed(UUID AgentID) - { - m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName); - - int count = 0; - while (queues.ContainsKey(AgentID) && queues[AgentID].Count() > 0 && count++ < 5) - { - Thread.Sleep(1000); - } - - lock (queues) - { - queues.Remove(AgentID); - } - List removeitems = new List(); - lock (m_AvatarQueueUUIDMapping) - { - foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys) - { - if (ky == AgentID) - { - removeitems.Add(ky); - } - } - - foreach (UUID ky in removeitems) - { - m_AvatarQueueUUIDMapping.Remove(ky); - m_scene.CommsManager.HttpServer.RemoveHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/"); - } - - } - UUID searchval = UUID.Zero; - - removeitems.Clear(); - - lock (m_QueueUUIDAvatarMapping) - { - foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys) - { - searchval = m_QueueUUIDAvatarMapping[ky]; - - if (searchval == AgentID) - { - removeitems.Add(ky); - } - } - - foreach (UUID ky in removeitems) - m_QueueUUIDAvatarMapping.Remove(ky); - - } - } - - private void MakeChildAgent(ScenePresence avatar) - { - //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName); - //lock (m_ids) - // { - //if (m_ids.ContainsKey(avatar.UUID)) - //{ - // close the event queue. - //m_ids[avatar.UUID] = -1; - //} - //} - } - - public void OnRegisterCaps(UUID agentID, Caps caps) - { - // Register an event queue for the client - - //m_log.DebugFormat( - // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", - // agentID, caps, m_scene.RegionInfo.RegionName); - - // Let's instantiate a Queue for this agent right now - TryGetQueue(agentID); - - string capsBase = "/CAPS/EQG/"; - UUID EventQueueGetUUID = UUID.Zero; - - lock (m_AvatarQueueUUIDMapping) - { - // Reuse open queues. The client does! - if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) - { - m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); - EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; - } - else - { - EventQueueGetUUID = UUID.Random(); - //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); - } - } - - lock (m_QueueUUIDAvatarMapping) - { - if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID)) - m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID); - } - - lock (m_AvatarQueueUUIDMapping) - { - if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID)) - m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID); - } - - // Register this as a caps handler - caps.RegisterHandler("EventQueueGet", - new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/", - delegate(Hashtable m_dhttpMethod) - { - return ProcessQueue(m_dhttpMethod, agentID, caps); - })); - - // This will persist this beyond the expiry of the caps handlers - m_scene.CommsManager.HttpServer.AddHTTPHandler( - capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePath2); - - Random rnd = new Random(System.Environment.TickCount); - lock (m_ids) - { - if (!m_ids.ContainsKey(agentID)) - m_ids.Add(agentID, rnd.Next(30000000)); - } - } - - public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps) - { - // TODO: this has to be redone to not busy-wait (and block the thread), - // TODO: as soon as we have a non-blocking way to handle HTTP-requests. - -// if (m_log.IsDebugEnabled) -// { -// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ "; -// foreach (object key in request.Keys) -// { -// debug += key.ToString() + "=" + request[key].ToString() + " "; -// } -// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name); -// } - - BlockingLLSDQueue queue = TryGetQueue(agentID); - OSD element = queue.Dequeue(15000); // 15s timeout - - Hashtable responsedata = new Hashtable(); - - int thisID = 0; - lock (m_ids) - thisID = m_ids[agentID]; - - if (element == null) - { - //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName); - if (thisID == -1) // close-request - { - m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName); - responsedata["int_response_code"] = 404; //501; //410; //404; - responsedata["content_type"] = "text/plain"; - responsedata["keepalive"] = false; - responsedata["str_response_string"] = "Closed EQG"; - return responsedata; - } - responsedata["int_response_code"] = 502; - responsedata["content_type"] = "text/plain"; - responsedata["keepalive"] = false; - responsedata["str_response_string"] = "Upstream error: "; - responsedata["error_status_text"] = "Upstream error:"; - responsedata["http_protocol_version"] = "HTTP/1.0"; - return responsedata; - } - - OSDArray array = new OSDArray(); - if (element == null) // didn't have an event in 15s - { - // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say! - array.Add(EventQueueHelper.KeepAliveEvent()); - m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); - } - else - { - array.Add(element); - while (queue.Count() > 0) - { - array.Add(queue.Dequeue(1)); - thisID++; - } - } - - OSDMap events = new OSDMap(); - events.Add("events", array); - - events.Add("id", new OSDInteger(thisID)); - lock (m_ids) - { - m_ids[agentID] = thisID + 1; - } - - responsedata["int_response_code"] = 200; - responsedata["content_type"] = "application/xml"; - responsedata["keepalive"] = false; - responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events); - //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]); - - return responsedata; - } - - public Hashtable EventQueuePath2(Hashtable request) - { - string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/",""); - // pull off the last "/" in the path. - Hashtable responsedata = new Hashtable(); - capuuid = capuuid.Substring(0, capuuid.Length - 1); - capuuid = capuuid.Replace("/CAPS/EQG/", ""); - UUID AvatarID = UUID.Zero; - UUID capUUID = UUID.Zero; - - // parse the path and search for the avatar with it registered - if (UUID.TryParse(capuuid, out capUUID)) - { - lock (m_QueueUUIDAvatarMapping) - { - if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) - { - AvatarID = m_QueueUUIDAvatarMapping[capUUID]; - } - } - if (AvatarID != UUID.Zero) - { - return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsHandlerForUser(AvatarID)); - } - else - { - responsedata["int_response_code"] = 404; - responsedata["content_type"] = "text/plain"; - responsedata["keepalive"] = false; - responsedata["str_response_string"] = "Not Found"; - responsedata["error_status_text"] = "Not Found"; - responsedata["http_protocol_version"] = "HTTP/1.0"; - return responsedata; - // return 404 - } - } - else - { - responsedata["int_response_code"] = 404; - responsedata["content_type"] = "text/plain"; - responsedata["keepalive"] = false; - responsedata["str_response_string"] = "Not Found"; - responsedata["error_status_text"] = "Not Found"; - responsedata["http_protocol_version"] = "HTTP/1.0"; - return responsedata; - // return 404 - } - - } - - public OSD EventQueueFallBack(string path, OSD request, string endpoint) - { - // This is a fallback element to keep the client from loosing EventQueueGet - // Why does CAPS fail sometimes!? - m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!"); - string capuuid = path.Replace("/CAPS/EQG/",""); - capuuid = capuuid.Substring(0, capuuid.Length - 1); - -// UUID AvatarID = UUID.Zero; - UUID capUUID = UUID.Zero; - if (UUID.TryParse(capuuid, out capUUID)) - { -/* Don't remove this yet code cleaners! - * Still testing this! - * - lock (m_QueueUUIDAvatarMapping) - { - if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) - { - AvatarID = m_QueueUUIDAvatarMapping[capUUID]; - } - } - - - if (AvatarID != UUID.Zero) - { - // Repair the CAP! - //OpenSim.Framework.Communications.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID); - //string capsBase = "/CAPS/EQG/"; - //caps.RegisterHandler("EventQueueGet", - //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/", - //delegate(Hashtable m_dhttpMethod) - //{ - // return ProcessQueue(m_dhttpMethod, AvatarID, caps); - //})); - // start new ID sequence. - Random rnd = new Random(System.Environment.TickCount); - lock (m_ids) - { - if (!m_ids.ContainsKey(AvatarID)) - m_ids.Add(AvatarID, rnd.Next(30000000)); - } - - - int thisID = 0; - lock (m_ids) - thisID = m_ids[AvatarID]; - - BlockingLLSDQueue queue = GetQueue(AvatarID); - OSDArray array = new OSDArray(); - LLSD element = queue.Dequeue(15000); // 15s timeout - if (element == null) - { - - array.Add(EventQueueHelper.KeepAliveEvent()); - } - else - { - array.Add(element); - while (queue.Count() > 0) - { - array.Add(queue.Dequeue(1)); - thisID++; - } - } - OSDMap events = new OSDMap(); - events.Add("events", array); - - events.Add("id", new LLSDInteger(thisID)); - - lock (m_ids) - { - m_ids[AvatarID] = thisID + 1; - } - - return events; - } - else - { - return new LLSD(); - } -* -*/ - } - else - { - //return new LLSD(); - } - - return new OSDString("shutdown404!"); - } - - public void DisableSimulator(ulong handle, UUID avatarID) - { - OSD item = EventQueueHelper.DisableSimulator(handle); - Enqueue(item, avatarID); - } - - public void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID) - { - OSD item = EventQueueHelper.EnableSimulator(handle, endPoint); - Enqueue(item, avatarID); - } - - public void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath) - { - OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath); - Enqueue(item, avatarID); - } - - public void TeleportFinishEvent(ulong regionHandle, byte simAccess, - IPEndPoint regionExternalEndPoint, - uint locationID, uint flags, string capsURL, - UUID avatarID) - { - OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint, - locationID, flags, capsURL, avatarID); - Enqueue(item, avatarID); - } - - public void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, - IPEndPoint newRegionExternalEndPoint, - string capsURL, UUID avatarID, UUID sessionID) - { - OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint, - capsURL, avatarID, sessionID); - Enqueue(item, avatarID); - } - - public void ChatterboxInvitation(UUID sessionID, string sessionName, - UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, - uint timeStamp, bool offline, int parentEstateID, Vector3 position, - uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) - { - OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog, - timeStamp, offline, parentEstateID, position, ttl, transactionID, - fromGroup, binaryBucket); - Enqueue(item, toAgent); - m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item); - - } - - public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, - bool isModerator, bool textMute) - { - OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat, - isModerator, textMute); - Enqueue(item, toAgent); - m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); - } - - public void ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket, UUID avatarID) - { - OSD item = Environment.EventQueueHelper.ParcelProperties(parcelPropertiesPacket); - Enqueue(item, avatarID); - } - - public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID) - { - OSD item = EventQueueHelper.GroupMembership(groupUpdate); - Enqueue(item, avatarID); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs b/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs deleted file mode 100644 index b38ddba..0000000 --- a/OpenSim/Region/Environment/Modules/Framework/EventQueue/EventQueueHelper.cs +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Net; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenMetaverse.StructuredData; - -namespace OpenSim.Region.Environment -{ - public class EventQueueHelper - { - private EventQueueHelper() {} // no construction possible, it's an utility class - - private static byte[] ulongToByteArray(ulong uLongValue) - { - // Reverse endianness of RegionHandle - return new byte[] - { - (byte)((uLongValue >> 56) % 256), - (byte)((uLongValue >> 48) % 256), - (byte)((uLongValue >> 40) % 256), - (byte)((uLongValue >> 32) % 256), - (byte)((uLongValue >> 24) % 256), - (byte)((uLongValue >> 16) % 256), - (byte)((uLongValue >> 8) % 256), - (byte)(uLongValue % 256) - }; - } - - private static byte[] uintToByteArray(uint uIntValue) - { - byte[] resultbytes = Utils.UIntToBytes(uIntValue); - if (BitConverter.IsLittleEndian) - Array.Reverse(resultbytes); - - return resultbytes; - } - - public static OSD buildEvent(string eventName, OSD eventBody) - { - OSDMap llsdEvent = new OSDMap(2); - llsdEvent.Add("message", new OSDString(eventName)); - llsdEvent.Add("body", eventBody); - - return llsdEvent; - } - - public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint) - { - OSDMap llsdSimInfo = new OSDMap(3); - - llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle))); - llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes())); - llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port)); - - OSDArray arr = new OSDArray(1); - arr.Add(llsdSimInfo); - - OSDMap llsdBody = new OSDMap(1); - llsdBody.Add("SimulatorInfo", arr); - - return buildEvent("EnableSimulator", llsdBody); - } - - public static OSD DisableSimulator(ulong handle) - { - //OSDMap llsdSimInfo = new OSDMap(1); - - //llsdSimInfo.Add("Handle", new OSDBinary(regionHandleToByteArray(handle))); - - //OSDArray arr = new OSDArray(1); - //arr.Add(llsdSimInfo); - - OSDMap llsdBody = new OSDMap(0); - //llsdBody.Add("SimulatorInfo", arr); - - return buildEvent("DisableSimulator", llsdBody); - } - - public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, - IPEndPoint newRegionExternalEndPoint, - string capsURL, UUID agentID, UUID sessionID) - { - OSDArray lookAtArr = new OSDArray(3); - lookAtArr.Add(OSD.FromReal(lookAt.X)); - lookAtArr.Add(OSD.FromReal(lookAt.Y)); - lookAtArr.Add(OSD.FromReal(lookAt.Z)); - - OSDArray positionArr = new OSDArray(3); - positionArr.Add(OSD.FromReal(pos.X)); - positionArr.Add(OSD.FromReal(pos.Y)); - positionArr.Add(OSD.FromReal(pos.Z)); - - OSDMap infoMap = new OSDMap(2); - infoMap.Add("LookAt", lookAtArr); - infoMap.Add("Position", positionArr); - - OSDArray infoArr = new OSDArray(1); - infoArr.Add(infoMap); - - OSDMap agentDataMap = new OSDMap(2); - agentDataMap.Add("AgentID", OSD.FromUUID(agentID)); - agentDataMap.Add("SessionID", OSD.FromUUID(sessionID)); - - OSDArray agentDataArr = new OSDArray(1); - agentDataArr.Add(agentDataMap); - - OSDMap regionDataMap = new OSDMap(4); - regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle))); - regionDataMap.Add("SeedCapability", OSD.FromString(capsURL)); - regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes())); - regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port)); - - OSDArray regionDataArr = new OSDArray(1); - regionDataArr.Add(regionDataMap); - - OSDMap llsdBody = new OSDMap(3); - llsdBody.Add("Info", infoArr); - llsdBody.Add("AgentData", agentDataArr); - llsdBody.Add("RegionData", regionDataArr); - - return buildEvent("CrossedRegion", llsdBody); - } - - public static OSD TeleportFinishEvent( - ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, - uint locationID, uint flags, string capsURL, UUID agentID) - { - OSDMap info = new OSDMap(); - info.Add("AgentID", OSD.FromUUID(agentID)); - info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this? - info.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(regionHandle))); - info.Add("SeedCapability", OSD.FromString(capsURL)); - info.Add("SimAccess", OSD.FromInteger(simAccess)); - info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); - info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); - info.Add("TeleportFlags", OSD.FromBinary(1L << 4)); // AgentManager.TeleportFlags.ViaLocation - - OSDArray infoArr = new OSDArray(); - infoArr.Add(info); - - OSDMap body = new OSDMap(); - body.Add("Info", infoArr); - - return buildEvent("TeleportFinish", body); - } - - public static OSD ScriptRunningReplyEvent(UUID objectID, UUID itemID, bool running, bool mono) - { - OSDMap script = new OSDMap(); - script.Add("ObjectID", OSD.FromUUID(objectID)); - script.Add("ItemID", OSD.FromUUID(itemID)); - script.Add("Running", OSD.FromBoolean(running)); - script.Add("Mono", OSD.FromBoolean(mono)); - - OSDArray scriptArr = new OSDArray(); - scriptArr.Add(script); - - OSDMap body = new OSDMap(); - body.Add("Script", scriptArr); - - return buildEvent("ScriptRunningReply", body); - } - - public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap) - { - OSDMap body = new OSDMap(3); - body.Add("agent-id", new OSDUUID(agentID)); - body.Add("sim-ip-and-port", new OSDString(simIpAndPort)); - body.Add("seed-capability", new OSDString(seedcap)); - - return buildEvent("EstablishAgentCommunication", body); - } - - public static OSD KeepAliveEvent() - { - return buildEvent("FAKEEVENT", new OSDMap()); - } - - public static OSD AgentParams(UUID agentID, bool checkEstate, int godLevel, bool limitedToEstate) - { - OSDMap body = new OSDMap(4); - - body.Add("agent_id", new OSDUUID(agentID)); - body.Add("check_estate", new OSDInteger(checkEstate ? 1 : 0)); - body.Add("god_level", new OSDInteger(godLevel)); - body.Add("limited_to_estate", new OSDInteger(limitedToEstate ? 1 : 0)); - - return body; - } - - public static OSD InstantMessageParams(UUID fromAgent, string message, UUID toAgent, - string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID, - Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) - { - OSDMap messageParams = new OSDMap(15); - messageParams.Add("type", new OSDInteger((int)dialog)); - - OSDArray positionArray = new OSDArray(3); - positionArray.Add(OSD.FromReal(position.X)); - positionArray.Add(OSD.FromReal(position.Y)); - positionArray.Add(OSD.FromReal(position.Z)); - messageParams.Add("position", positionArray); - - messageParams.Add("region_id", new OSDUUID(UUID.Zero)); - messageParams.Add("to_id", new OSDUUID(toAgent)); - messageParams.Add("source", new OSDInteger(0)); - - OSDMap data = new OSDMap(1); - data.Add("binary_bucket", OSD.FromBinary(binaryBucket)); - messageParams.Add("data", data); - messageParams.Add("message", new OSDString(message)); - messageParams.Add("id", new OSDUUID(transactionID)); - messageParams.Add("from_name", new OSDString(fromName)); - messageParams.Add("timestamp", new OSDInteger((int)timeStamp)); - messageParams.Add("offline", new OSDInteger(offline ? 1 : 0)); - messageParams.Add("parent_estate_id", new OSDInteger(parentEstateID)); - messageParams.Add("ttl", new OSDInteger((int)ttl)); - messageParams.Add("from_id", new OSDUUID(fromAgent)); - messageParams.Add("from_group", new OSDInteger(fromGroup ? 1 : 0)); - - return messageParams; - } - - public static OSD InstantMessage(UUID fromAgent, string message, UUID toAgent, - string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID, - Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket, - bool checkEstate, int godLevel, bool limitedToEstate) - { - OSDMap im = new OSDMap(2); - im.Add("message_params", InstantMessageParams(fromAgent, message, toAgent, - fromName, dialog, timeStamp, offline, parentEstateID, - position, ttl, transactionID, fromGroup, binaryBucket)); - - im.Add("agent_params", AgentParams(fromAgent, checkEstate, godLevel, limitedToEstate)); - - return im; - } - - - public static OSD ChatterboxInvitation(UUID sessionID, string sessionName, - UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, - uint timeStamp, bool offline, int parentEstateID, Vector3 position, - uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) - { - OSDMap body = new OSDMap(5); - body.Add("session_id", new OSDUUID(sessionID)); - body.Add("from_name", new OSDString(fromName)); - body.Add("session_name", new OSDString(sessionName)); - body.Add("from_id", new OSDUUID(fromAgent)); - - body.Add("instantmessage", InstantMessage(fromAgent, message, toAgent, - fromName, dialog, timeStamp, offline, parentEstateID, position, - ttl, transactionID, fromGroup, binaryBucket, true, 0, true)); - - OSDMap chatterboxInvitation = new OSDMap(2); - chatterboxInvitation.Add("message", new OSDString("ChatterBoxInvitation")); - chatterboxInvitation.Add("body", body); - return chatterboxInvitation; - } - - public static OSD ChatterBoxSessionAgentListUpdates(UUID sessionID, - UUID agentID, bool canVoiceChat, bool isModerator, bool textMute) - { - OSDMap body = new OSDMap(); - OSDMap agentUpdates = new OSDMap(); - OSDMap infoDetail = new OSDMap(); - OSDMap mutes = new OSDMap(); - - mutes.Add("text", OSD.FromBoolean(textMute)); - infoDetail.Add("can_voice_chat", OSD.FromBoolean(canVoiceChat)); - infoDetail.Add("is_moderator", OSD.FromBoolean(isModerator)); - infoDetail.Add("mutes", mutes); - OSDMap info = new OSDMap(); - info.Add("info", infoDetail); - agentUpdates.Add(agentID.ToString(), info); - body.Add("agent_updates", agentUpdates); - body.Add("session_id", OSD.FromUUID(sessionID)); - body.Add("updates", new OSD()); - - OSDMap chatterBoxSessionAgentListUpdates = new OSDMap(); - chatterBoxSessionAgentListUpdates.Add("message", OSD.FromString("ChatterBoxSessionAgentListUpdates")); - chatterBoxSessionAgentListUpdates.Add("body", body); - - return chatterBoxSessionAgentListUpdates; - } - - public static OSD ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket) - { - OSDMap parcelProperties = new OSDMap(); - OSDMap body = new OSDMap(); - - OSDArray ageVerificationBlock = new OSDArray(); - OSDMap ageVerificationMap = new OSDMap(); - ageVerificationMap.Add("RegionDenyAgeUnverified", - OSD.FromBoolean(parcelPropertiesPacket.AgeVerificationBlock.RegionDenyAgeUnverified)); - ageVerificationBlock.Add(ageVerificationMap); - body.Add("AgeVerificationBlock", ageVerificationBlock); - - // LL sims send media info in this event queue message but it's not in the UDP - // packet we construct this event queue message from. This should be refactored in - // other areas of the code so it can all be send in the same message. Until then we will - // still send the media info via UDP - - //OSDArray mediaData = new OSDArray(); - //OSDMap mediaDataMap = new OSDMap(); - //mediaDataMap.Add("MediaDesc", OSD.FromString("")); - //mediaDataMap.Add("MediaHeight", OSD.FromInteger(0)); - //mediaDataMap.Add("MediaLoop", OSD.FromInteger(0)); - //mediaDataMap.Add("MediaType", OSD.FromString("type/type")); - //mediaDataMap.Add("MediaWidth", OSD.FromInteger(0)); - //mediaDataMap.Add("ObscureMedia", OSD.FromInteger(0)); - //mediaDataMap.Add("ObscureMusic", OSD.FromInteger(0)); - //mediaData.Add(mediaDataMap); - //body.Add("MediaData", mediaData); - - OSDArray parcelData = new OSDArray(); - OSDMap parcelDataMap = new OSDMap(); - OSDArray AABBMax = new OSDArray(3); - AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.X)); - AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Y)); - AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Z)); - parcelDataMap.Add("AABBMax", AABBMax); - - OSDArray AABBMin = new OSDArray(3); - AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.X)); - AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Y)); - AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Z)); - parcelDataMap.Add("AABBMin", AABBMin); - - parcelDataMap.Add("Area", OSD.FromInteger(parcelPropertiesPacket.ParcelData.Area)); - parcelDataMap.Add("AuctionID", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.AuctionID))); - parcelDataMap.Add("AuthBuyerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.AuthBuyerID)); - parcelDataMap.Add("Bitmap", OSD.FromBinary(parcelPropertiesPacket.ParcelData.Bitmap)); - parcelDataMap.Add("Category", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Category)); - parcelDataMap.Add("ClaimDate", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimDate)); - parcelDataMap.Add("ClaimPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimPrice)); - parcelDataMap.Add("Desc", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc))); - parcelDataMap.Add("GroupID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.GroupID)); - parcelDataMap.Add("GroupPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.GroupPrims)); - parcelDataMap.Add("IsGroupOwned", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.IsGroupOwned)); - parcelDataMap.Add("LandingType", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LandingType)); - parcelDataMap.Add("LocalID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LocalID)); - parcelDataMap.Add("MaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.MaxPrims)); - parcelDataMap.Add("MediaAutoScale", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.MediaAutoScale)); - parcelDataMap.Add("MediaID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.MediaID)); - parcelDataMap.Add("MediaURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL))); - parcelDataMap.Add("MusicURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL))); - parcelDataMap.Add("Name", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name))); - parcelDataMap.Add("OtherCleanTime", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCleanTime)); - parcelDataMap.Add("OtherCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCount)); - parcelDataMap.Add("OtherPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherPrims)); - parcelDataMap.Add("OwnerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.OwnerID)); - parcelDataMap.Add("OwnerPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OwnerPrims)); - parcelDataMap.Add("ParcelFlags", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.ParcelFlags))); - parcelDataMap.Add("ParcelPrimBonus", OSD.FromReal(parcelPropertiesPacket.ParcelData.ParcelPrimBonus)); - parcelDataMap.Add("PassHours", OSD.FromReal(parcelPropertiesPacket.ParcelData.PassHours)); - parcelDataMap.Add("PassPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PassPrice)); - parcelDataMap.Add("PublicCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PublicCount)); - parcelDataMap.Add("RegionDenyAnonymous", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyAnonymous)); - parcelDataMap.Add("RegionDenyIdentified", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyIdentified)); - parcelDataMap.Add("RegionDenyTransacted", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyTransacted)); - - parcelDataMap.Add("RegionPushOverride", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionPushOverride)); - parcelDataMap.Add("RentPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RentPrice)); - parcelDataMap.Add("RequestResult", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RequestResult)); - parcelDataMap.Add("SalePrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SalePrice)); - parcelDataMap.Add("SelectedPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelectedPrims)); - parcelDataMap.Add("SelfCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelfCount)); - parcelDataMap.Add("SequenceID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SequenceID)); - parcelDataMap.Add("SimWideMaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideMaxPrims)); - parcelDataMap.Add("SimWideTotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideTotalPrims)); - parcelDataMap.Add("SnapSelection", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.SnapSelection)); - parcelDataMap.Add("SnapshotID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.SnapshotID)); - parcelDataMap.Add("Status", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Status)); - parcelDataMap.Add("TotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.TotalPrims)); - - OSDArray UserLocation = new OSDArray(3); - UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.X)); - UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Y)); - UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Z)); - parcelDataMap.Add("UserLocation", UserLocation); - - OSDArray UserLookAt = new OSDArray(3); - UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.X)); - UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Y)); - UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Z)); - parcelDataMap.Add("UserLookAt", UserLookAt); - - parcelData.Add(parcelDataMap); - body.Add("ParcelData", parcelData); - parcelProperties.Add("body", body); - parcelProperties.Add("message", OSD.FromString("ParcelProperties")); - - return parcelProperties; - } - - public static OSD GroupMembership(AgentGroupDataUpdatePacket groupUpdatePacket) - { - OSDMap groupUpdate = new OSDMap(); - groupUpdate.Add("message", OSD.FromString("AgentGroupDataUpdate")); - - OSDMap body = new OSDMap(); - OSDArray agentData = new OSDArray(); - OSDMap agentDataMap = new OSDMap(); - agentDataMap.Add("AgentID", OSD.FromUUID(groupUpdatePacket.AgentData.AgentID)); - agentData.Add(agentDataMap); - body.Add("AgentData", agentData); - - OSDArray groupData = new OSDArray(); - - foreach (AgentGroupDataUpdatePacket.GroupDataBlock groupDataBlock in groupUpdatePacket.GroupData) - { - OSDMap groupDataMap = new OSDMap(); - groupDataMap.Add("ListInProfile", OSD.FromBoolean(false)); - groupDataMap.Add("GroupID", OSD.FromUUID(groupDataBlock.GroupID)); - groupDataMap.Add("GroupInsigniaID", OSD.FromUUID(groupDataBlock.GroupInsigniaID)); - groupDataMap.Add("Contribution", OSD.FromInteger(groupDataBlock.Contribution)); - groupDataMap.Add("GroupPowers", OSD.FromBinary(ulongToByteArray(groupDataBlock.GroupPowers))); - groupDataMap.Add("GroupName", OSD.FromString(Utils.BytesToString(groupDataBlock.GroupName))); - groupDataMap.Add("AcceptNotices", OSD.FromBoolean(groupDataBlock.AcceptNotices)); - - groupData.Add(groupDataMap); - - } - body.Add("GroupData", groupData); - groupUpdate.Add("body", body); - - return groupUpdate; - } - - } -} diff --git a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs b/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs deleted file mode 100644 index b6114e8..0000000 --- a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Command.cs +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Framework.InterfaceCommander -{ - /// - /// A single function call encapsulated in a class which enforces arguments when passing around as Object[]'s. - /// Used for console commands and script API generation - /// - public class Command : ICommand - { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private List m_args = new List(); - - private Action m_command; - private string m_help; - private string m_name; - private CommandIntentions m_intentions; //A permission type system could implement this and know what a command intends on doing. - - public Command(string name, CommandIntentions intention, Action command, string help) - { - m_name = name; - m_command = command; - m_help = help; - m_intentions = intention; - } - - #region ICommand Members - - public void AddArgument(string name, string helptext, string type) - { - m_args.Add(new CommandArgument(name, helptext, type)); - } - - public string Name - { - get { return m_name; } - } - - public CommandIntentions Intentions - { - get { return m_intentions; } - } - - public string Help - { - get { return m_help; } - } - - public Dictionary Arguments - { - get - { - Dictionary tmp = new Dictionary(); - foreach (CommandArgument arg in m_args) - { - tmp.Add(arg.Name, arg.ArgumentType); - } - return tmp; - } - } - - public string ShortHelp() - { - string help = m_name; - - foreach (CommandArgument arg in m_args) - { - help += " <" + arg.Name + ">"; - } - - return help; - } - - public void ShowConsoleHelp() - { - Console.WriteLine("== " + Name + " =="); - Console.WriteLine(m_help); - Console.WriteLine("= Parameters ="); - foreach (CommandArgument arg in m_args) - { - Console.WriteLine("* " + arg.Name + " (" + arg.ArgumentType + ")"); - Console.WriteLine("\t" + arg.HelpText); - } - } - - public void Run(Object[] args) - { - Object[] cleanArgs = new Object[m_args.Count]; - - if (args.Length < cleanArgs.Length) - { - Console.WriteLine("ERROR: Missing " + (cleanArgs.Length - args.Length) + " argument(s)"); - ShowConsoleHelp(); - return; - } - if (args.Length > cleanArgs.Length) - { - Console.WriteLine("ERROR: Too many arguments for this command. Type ' help' for help."); - return; - } - - int i = 0; - foreach (Object arg in args) - { - if (string.IsNullOrEmpty(arg.ToString())) - { - Console.WriteLine("ERROR: Empty arguments are not allowed"); - return; - } - try - { - switch (m_args[i].ArgumentType) - { - case "String": - m_args[i].ArgumentValue = arg.ToString(); - break; - case "Integer": - m_args[i].ArgumentValue = Int32.Parse(arg.ToString()); - break; - case "Double": - m_args[i].ArgumentValue = Double.Parse(arg.ToString()); - break; - case "Boolean": - m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); - break; - default: - Console.WriteLine("ERROR: Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); - break; - } - } - catch (FormatException) - { - Console.WriteLine("ERROR: Argument number " + (i + 1) + - " (" + m_args[i].Name + ") must be a valid " + - m_args[i].ArgumentType.ToLower() + "."); - return; - } - cleanArgs[i] = m_args[i].ArgumentValue; - - i++; - } - - m_command.Invoke(cleanArgs); - } - - #endregion - } - - /// - /// A single command argument, contains name, type and at runtime, value. - /// - public class CommandArgument - { - private string m_help; - private string m_name; - private string m_type; - private Object m_val; - - public CommandArgument(string name, string help, string type) - { - m_name = name; - m_help = help; - m_type = type; - } - - public string Name - { - get { return m_name; } - } - - public string HelpText - { - get { return m_help; } - } - - public string ArgumentType - { - get { return m_type; } - } - - public Object ArgumentValue - { - get { return m_val; } - set { m_val = value; } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs b/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs deleted file mode 100644 index cd66295..0000000 --- a/OpenSim/Region/Environment/Modules/Framework/InterfaceCommander/Commander.cs +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Framework.InterfaceCommander -{ - /// - /// A class to enable modules to register console and script commands, which enforces typing and valid input. - /// - public class Commander : ICommander - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Used in runtime class generation - /// - private string m_generatedApiClassName; - - public string Name - { - get { return m_name; } - } - private string m_name; - - public string Help - { - get - { - StringBuilder sb = new StringBuilder(); - - sb.AppendLine("=== " + m_name + " ==="); - - foreach (ICommand com in m_commands.Values) - { - sb.AppendLine("* " + Name + " " + com.Name + " - " + com.Help); - } - - return sb.ToString(); - } - } - - /// - /// Constructor - /// - /// - public Commander(string name) - { - m_name = name; - m_generatedApiClassName = m_name[0].ToString().ToUpper(); - - if (m_name.Length > 1) - m_generatedApiClassName += m_name.Substring(1); - } - - public Dictionary Commands - { - get { return m_commands; } - } - private Dictionary m_commands = new Dictionary(); - - #region ICommander Members - - public void RegisterCommand(string commandName, ICommand command) - { - m_commands[commandName] = command; - } - - /// - /// Generates a runtime C# class which can be compiled and inserted via reflection to enable modules to register new script commands - /// - /// Returns C# source code to create a binding - public string GenerateRuntimeAPI() - { - string classSrc = "\n\tpublic class " + m_generatedApiClassName + " {\n"; - foreach (ICommand com in m_commands.Values) - { - classSrc += "\tpublic void " + EscapeRuntimeAPICommand(com.Name) + "( "; - foreach (KeyValuePair arg in com.Arguments) - { - classSrc += arg.Value + " " + Util.Md5Hash(arg.Key) + ","; - } - classSrc = classSrc.Remove(classSrc.Length - 1); // Delete the last comma - classSrc += " )\n\t{\n"; - classSrc += "\t\tObject[] args = new Object[" + com.Arguments.Count.ToString() + "];\n"; - int i = 0; - foreach (KeyValuePair arg in com.Arguments) - { - classSrc += "\t\targs[" + i.ToString() + "] = " + Util.Md5Hash(arg.Key) + " " + ";\n"; - i++; - } - classSrc += "\t\tGetCommander(\"" + m_name + "\").Run(\"" + com.Name + "\", args);\n"; - classSrc += "\t}\n"; - } - classSrc += "}\n"; - - return classSrc; - } - - /// - /// Runs a specified function with attached arguments - /// *** DO NOT CALL DIRECTLY. *** - /// Call ProcessConsoleCommand instead if handling human input. - /// - /// The function name to call - /// The function parameters - public void Run(string function, object[] args) - { - m_commands[function].Run(args); - } - - public void ProcessConsoleCommand(string function, string[] args) - { - if (m_commands.ContainsKey(function)) - { - if (args.Length > 0 && args[0] == "help") - { - m_commands[function].ShowConsoleHelp(); - } - else - { - m_commands[function].Run(args); - } - } - else - { - if (function == "api") - { - m_log.Info(GenerateRuntimeAPI()); - } - else - { - if (function != "help") - Console.WriteLine("ERROR: Invalid command - No such command exists"); - - Console.Write(Help); - } - } - } - - #endregion - - private string EscapeRuntimeAPICommand(string command) - { - command = command.Replace('-', '_'); - StringBuilder tmp = new StringBuilder(command); - tmp[0] = tmp[0].ToString().ToUpper().ToCharArray()[0]; - - return tmp.ToString(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs deleted file mode 100644 index edf1231..0000000 --- a/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Grid.Interregion -{ - public interface IInterregionModule - { - void RegisterMethod(T e); - bool HasInterface(Location loc); - T RequestInterface(Location loc); - T[] RequestInterface(); - Location GetLocationByDirection(Scene scene, InterregionModule.Direction dir); - void internal_CreateRemotingObjects(); - void RegisterRemoteRegion(string uri); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs deleted file mode 100644 index cb571e4..0000000 --- a/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Channels; -using System.Runtime.Remoting.Channels.Tcp; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Grid.Interregion -{ - public class InterregionModule : IInterregionModule, IRegionModule - { - #region Direction enum - - public enum Direction - { - North, - NorthEast, - East, - SouthEast, - South, - SouthWest, - West, - NorthWest - } - - #endregion - - private readonly Dictionary m_interfaces = new Dictionary(); - private readonly Object m_lockObject = new object(); - private readonly List m_myLocations = new List(); - - private readonly Dictionary m_neighbourInterfaces = new Dictionary(); - private readonly Dictionary m_neighbourRemote = new Dictionary(); - // private IConfigSource m_config; - private const bool m_enabled = false; - - private RemotingObject m_myRemote; - private TcpChannel m_tcpChannel; - private int m_tcpPort = 10101; - - #region IInterregionModule Members - - public void internal_CreateRemotingObjects() - { - lock (m_lockObject) - { - if (m_tcpChannel == null) - { - m_myRemote = new RemotingObject(m_interfaces, m_myLocations.ToArray()); - m_tcpChannel = new TcpChannel(m_tcpPort); - - ChannelServices.RegisterChannel(m_tcpChannel, false); - RemotingServices.Marshal(m_myRemote, "OpenSimRemote2", typeof (RemotingObject)); - } - } - } - - public void RegisterMethod(T e) - { - m_interfaces[typeof (T)] = e; - } - - public bool HasInterface(Location loc) - { - foreach (string val in m_neighbourInterfaces[loc]) - { - if (val == typeof (T).FullName) - { - return true; - } - } - return false; - } - - public T RequestInterface(Location loc) - { - if (m_neighbourRemote.ContainsKey(loc)) - { - return m_neighbourRemote[loc].RequestInterface(); - } - throw new IndexOutOfRangeException("No neighbour availible at that location"); - } - - public T[] RequestInterface() - { - List m_t = new List(); - foreach (RemotingObject remote in m_neighbourRemote.Values) - { - try - { - m_t.Add(remote.RequestInterface()); - } - catch (NotSupportedException) - { - } - } - return m_t.ToArray(); - } - - public Location GetLocationByDirection(Scene scene, Direction dir) - { - return new Location(0, 0); - } - - public void RegisterRemoteRegion(string uri) - { - RegisterRemotingInterface((RemotingObject) Activator.GetObject(typeof (RemotingObject), uri)); - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - m_myLocations.Add(new Location((int) scene.RegionInfo.RegionLocX, - (int) scene.RegionInfo.RegionLocY)); - // m_config = source; - - scene.RegisterModuleInterface(this); - } - - public void PostInitialise() - { - // Commenting out to remove 'unreachable code' warning since m_enabled is never true -// if (m_enabled) -// { -// try -// { -// m_tcpPort = m_config.Configs["Comms"].GetInt("remoting_port", m_tcpPort); -// } -// catch -// { -// } -// -// internal_CreateRemotingObjects(); -// } - } - - public void Close() - { - if (null != m_tcpChannel) - ChannelServices.UnregisterChannel(m_tcpChannel); - } - - public string Name - { - get { return "InterregionModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void RegisterRemotingInterface(RemotingObject remote) - { - Location[] locs = remote.GetLocations(); - string[] interfaces = remote.GetInterfaces(); - foreach (Location loc in locs) - { - m_neighbourInterfaces[loc] = interfaces; - m_neighbourRemote[loc] = remote; - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs deleted file mode 100644 index 47357d2..0000000 --- a/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenSim.Framework; - -namespace OpenSim.Region.Environment.Modules.Grid.Interregion -{ - public class RemotingObject : MarshalByRefObject - { - private readonly Location[] m_coords; - private readonly Dictionary m_interfaces = new Dictionary(); - - public RemotingObject(Dictionary myInterfaces, Location[] coords) - { - m_interfaces = myInterfaces; - m_coords = coords; - } - - public Location[] GetLocations() - { - return (Location[]) m_coords.Clone(); - } - - public string[] GetInterfaces() - { - string[] interfaces = new string[m_interfaces.Count]; - int i = 0; - - foreach (KeyValuePair pair in m_interfaces) - { - interfaces[i++] = pair.Key.FullName; - } - - return interfaces; - } - - /// - /// Returns a registered interface availible to neighbouring regions. - /// - /// The type of interface you wish to request - /// A MarshalByRefObject inherited from this region inheriting the interface requested. - /// All registered interfaces MUST inherit from MarshalByRefObject and use only serialisable types. - public T RequestInterface() - { - if (m_interfaces.ContainsKey(typeof (T))) - return (T) m_interfaces[typeof (T)]; - - throw new NotSupportedException("No such interface registered."); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs b/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs deleted file mode 100644 index 4cb1c20..0000000 --- a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneAssetService.cs +++ /dev/null @@ -1,201 +0,0 @@ -/** - * Copyright (c) 2008, Contributors. All rights reserved. - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of the Organizations nor the names of Individual - * Contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -using System; -using System.Collections.Generic; -using System.Net; -using System.Reflection; - -using log4net; -using Nini.Config; - -using OpenMetaverse; - -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Grid.AssetServer; -using OpenSim.Data; - -namespace OpenSim.Region.Environment.Modules.Hypergrid -{ - public class HGStandaloneAssetService : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static bool initialized = false; - private static bool enabled = false; - - Scene m_scene; - //AssetService m_assetService; - - #region IRegionModule interface - - public void Initialise(Scene scene, IConfigSource config) - { - if (!initialized) - { - initialized = true; - m_scene = scene; - - // This module is only on for standalones in hypergrid mode - enabled = !config.Configs["Startup"].GetBoolean("gridmode", true) && config.Configs["Startup"].GetBoolean("hypergrid", false); - } - } - - public void PostInitialise() - { - if (enabled) - { - m_log.Info("[HGStandaloneAssetService]: Starting..."); - - //m_assetService = new AssetService(m_scene); - new AssetService(m_scene); - } - } - - public void Close() - { - } - - public string Name - { - get { return "HGStandaloneAssetService"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - } - - public class AssetService - { - private IUserService m_userService; - private bool m_doLookup = false; - - public bool DoLookup - { - get { return m_doLookup; } - set { m_doLookup = value; } - } - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public AssetService(Scene m_scene) - { - AddHttpHandlers(m_scene); - m_userService = m_scene.CommsManager.UserService; - } - - protected void AddHttpHandlers(Scene m_scene) - { - IAssetDataPlugin m_assetProvider = ((AssetServerBase)m_scene.AssetCache.AssetServer).AssetProviderPlugin; - - BaseHttpServer httpServer = m_scene.CommsManager.HttpServer; - httpServer.AddStreamHandler(new GetAssetStreamHandler(m_assetProvider)); - httpServer.AddStreamHandler(new PostAssetStreamHandler(m_assetProvider)); - - } - - ///// - ///// Check that the source of an inventory request is one that we trust. - ///// - ///// - ///// - //public bool CheckTrustSource(IPEndPoint peer) - //{ - // if (m_doLookup) - // { - // m_log.InfoFormat("[GRID AGENT INVENTORY]: Checking trusted source {0}", peer); - // UriBuilder ub = new UriBuilder(m_userserver_url); - // IPAddress[] uaddrs = Dns.GetHostAddresses(ub.Host); - // foreach (IPAddress uaddr in uaddrs) - // { - // if (uaddr.Equals(peer.Address)) - // { - // return true; - // } - // } - - // m_log.WarnFormat( - // "[GRID AGENT INVENTORY]: Rejecting request since source {0} was not in the list of trusted sources", - // peer); - - // return false; - // } - // else - // { - // return true; - // } - //} - - /// - /// Check that the source of an inventory request for a particular agent is a current session belonging to - /// that agent. - /// - /// - /// - /// - public bool CheckAuthSession(string session_id, string avatar_id) - { - if (m_doLookup) - { - m_log.InfoFormat("[HGStandaloneInvService]: checking authed session {0} {1}", session_id, avatar_id); - UUID userID = UUID.Zero; - UUID sessionID = UUID.Zero; - UUID.TryParse(avatar_id, out userID); - UUID.TryParse(session_id, out sessionID); - if (userID.Equals(UUID.Zero) || sessionID.Equals(UUID.Zero)) - { - m_log.Info("[HGStandaloneInvService]: Invalid user or session id " + avatar_id + "; " + session_id); - return false; - } - UserProfileData userProfile = m_userService.GetUserProfile(userID); - if (userProfile != null && userProfile.CurrentAgent != null && - userProfile.CurrentAgent.SessionID == sessionID) - { - m_log.Info("[HGStandaloneInvService]: user is logged in and session is valid. Authorizing access."); - return true; - } - - m_log.Warn("[HGStandaloneInvService]: unknown user or session_id, request rejected"); - return false; - } - else - { - return true; - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs b/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs deleted file mode 100644 index 54ba761..0000000 --- a/OpenSim/Region/Environment/Modules/Hypergrid/HGStandaloneInventoryService.cs +++ /dev/null @@ -1,314 +0,0 @@ -/** - * Copyright (c) 2008, Contributors. All rights reserved. - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of the Organizations nor the names of Individual - * Contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -using System; -using System.Collections.Generic; -using System.Net; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Hypergrid -{ - public class HGStandaloneInventoryService : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static bool initialized = false; - private static bool enabled = false; - - Scene m_scene; - //InventoryService m_inventoryService; - - #region IRegionModule interface - - public void Initialise(Scene scene, IConfigSource config) - { - if (!initialized) - { - initialized = true; - m_scene = scene; - - // This module is only on for standalones - enabled = !config.Configs["Startup"].GetBoolean("gridmode", true) && config.Configs["Startup"].GetBoolean("hypergrid", false); - } - } - - public void PostInitialise() - { - if (enabled) - { - m_log.Info("[HGStandaloneInvService]: Starting..."); - //m_inventoryService = new InventoryService(m_scene); - new InventoryService(m_scene); - } - } - - public void Close() - { - } - - public string Name - { - get { return "HGStandaloneInventoryService"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - } - - public class InventoryService - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private InventoryServiceBase m_inventoryService; - private IUserService m_userService; - private bool m_doLookup = false; - - public bool DoLookup - { - get { return m_doLookup; } - set { m_doLookup = value; } - } - - public InventoryService(Scene m_scene) - { - m_inventoryService = (InventoryServiceBase)m_scene.CommsManager.SecureInventoryService; - m_userService = m_scene.CommsManager.UserService; - AddHttpHandlers(m_scene); - } - - protected void AddHttpHandlers(Scene m_scene) - { - BaseHttpServer httpServer = m_scene.CommsManager.HttpServer; - - httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/GetInventory/", GetUserInventory, CheckAuthSession)); - - httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/NewFolder/", m_inventoryService.AddFolder, CheckAuthSession)); - - httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/UpdateFolder/", m_inventoryService.UpdateFolder, CheckAuthSession)); - - httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/MoveFolder/", m_inventoryService.MoveFolder, CheckAuthSession)); - - httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/PurgeFolder/", m_inventoryService.PurgeFolder, CheckAuthSession)); - - httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/NewItem/", m_inventoryService.AddItem, CheckAuthSession)); - - httpServer.AddStreamHandler( - new RestDeserialiseSecureHandler( - "POST", "/DeleteItem/", m_inventoryService.DeleteItem, CheckAuthSession)); - - //// WARNING: Root folders no longer just delivers the root and immediate child folders (e.g - //// system folders such as Objects, Textures), but it now returns the entire inventory skeleton. - //// It would have been better to rename this request, but complexities in the BaseHttpServer - //// (e.g. any http request not found is automatically treated as an xmlrpc request) make it easier - //// to do this for now. - //m_scene.AddStreamHandler( - // new RestDeserialiseTrustedHandler> - // ("POST", "/RootFolders/", GetInventorySkeleton, CheckTrustSource)); - - //// for persistent active gestures - //m_scene.AddStreamHandler( - // new RestDeserialiseTrustedHandler> - // ("POST", "/ActiveGestures/", GetActiveGestures, CheckTrustSource)); - } - - - ///// - ///// Check that the source of an inventory request is one that we trust. - ///// - ///// - ///// - //public bool CheckTrustSource(IPEndPoint peer) - //{ - // if (m_doLookup) - // { - // m_log.InfoFormat("[GRID AGENT INVENTORY]: Checking trusted source {0}", peer); - // UriBuilder ub = new UriBuilder(m_userserver_url); - // IPAddress[] uaddrs = Dns.GetHostAddresses(ub.Host); - // foreach (IPAddress uaddr in uaddrs) - // { - // if (uaddr.Equals(peer.Address)) - // { - // return true; - // } - // } - - // m_log.WarnFormat( - // "[GRID AGENT INVENTORY]: Rejecting request since source {0} was not in the list of trusted sources", - // peer); - - // return false; - // } - // else - // { - // return true; - // } - //} - - /// - /// Check that the source of an inventory request for a particular agent is a current session belonging to - /// that agent. - /// - /// - /// - /// - public bool CheckAuthSession(string session_id, string avatar_id) - { - if (m_doLookup) - { - m_log.InfoFormat("[HGStandaloneInvService]: checking authed session {0} {1}", session_id, avatar_id); - UUID userID = UUID.Zero; - UUID sessionID = UUID.Zero; - UUID.TryParse(avatar_id, out userID); - UUID.TryParse(session_id, out sessionID); - if (userID.Equals(UUID.Zero) || sessionID.Equals(UUID.Zero)) - { - m_log.Info("[HGStandaloneInvService]: Invalid user or session id " + avatar_id + "; " + session_id); - return false; - } - UserProfileData userProfile = m_userService.GetUserProfile(userID); - if (userProfile != null && userProfile.CurrentAgent != null && - userProfile.CurrentAgent.SessionID == sessionID) - { - m_log.Info("[HGStandaloneInvService]: user is logged in and session is valid. Authorizing access."); - return true; - } - - m_log.Warn("[HGStandaloneInvService]: unknown user or session_id, request rejected"); - return false; - } - else - { - return true; - } - } - - - /// - /// Return a user's entire inventory - /// - /// - /// The user's inventory. If an inventory cannot be found then an empty collection is returned. - public InventoryCollection GetUserInventory(Guid rawUserID) - { - UUID userID = new UUID(rawUserID); - - m_log.Info("[HGStandaloneInvService]: Processing request for inventory of " + userID); - - // Uncomment me to simulate a slow responding inventory server - //Thread.Sleep(16000); - - InventoryCollection invCollection = new InventoryCollection(); - - List allFolders = ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID); - - if (null == allFolders) - { - m_log.WarnFormat("[HGStandaloneInvService]: No inventory found for user {0}", rawUserID); - - return invCollection; - } - - List allItems = new List(); - - foreach (InventoryFolderBase folder in allFolders) - { - List items = ((InventoryServiceBase)m_inventoryService).RequestFolderItems(folder.ID); - - if (items != null) - { - allItems.InsertRange(0, items); - } - } - - invCollection.UserID = userID; - invCollection.Folders = allFolders; - invCollection.Items = allItems; - - // foreach (InventoryFolderBase folder in invCollection.Folders) - // { - // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back folder {0} {1}", folder.Name, folder.ID); - // } - // - // foreach (InventoryItemBase item in invCollection.Items) - // { - // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder); - // } - - m_log.InfoFormat( - "[HGStandaloneInvService]: Sending back inventory response to user {0} containing {1} folders and {2} items", - invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count); - - return invCollection; - } - - /// - /// Guid to UUID wrapper for same name IInventoryServices method - /// - /// - /// - public List GetInventorySkeleton(Guid rawUserID) - { - UUID userID = new UUID(rawUserID); - return ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID); - } - - public List GetActiveGestures(Guid rawUserID) - { - UUID userID = new UUID(rawUserID); - - m_log.InfoFormat("[HGStandaloneInvService]: fetching active gestures for user {0}", userID); - - return ((InventoryServiceBase)m_inventoryService).GetActiveGestures(userID); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs deleted file mode 100644 index 1d9182e..0000000 --- a/OpenSim/Region/Environment/Modules/Hypergrid/HGWorldMapModule.cs +++ /dev/null @@ -1,178 +0,0 @@ -/** - * Copyright (c) 2008, Contributors. All rights reserved. - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * Neither the name of the Organizations nor the names of Individual - * Contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Net; -using System.Reflection; -using System.Threading; -using OpenMetaverse; -using OpenMetaverse.Imaging; -using OpenMetaverse.StructuredData; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; - -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Communications.Capabilities; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Types; -using OpenSim.Region.Environment.Modules.World.WorldMap; -using Caps = OpenSim.Framework.Communications.Capabilities.Caps; - -using OSD = OpenMetaverse.StructuredData.OSD; -using OSDMap = OpenMetaverse.StructuredData.OSDMap; -using OSDArray = OpenMetaverse.StructuredData.OSDArray; - -namespace OpenSim.Region.Environment.Modules.Hypergrid -{ - public class HGWorldMapModule : WorldMapModule, IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - #region IRegionModule Members - - public override void Initialise(Scene scene, IConfigSource config) - { - IConfig startupConfig = config.Configs["Startup"]; - if (startupConfig.GetString("WorldMapModule", "WorldMap") == "HGWorldMap") - m_Enabled = true; - - if (!m_Enabled) - return; - m_log.Info("[HGMap] Initializing..."); - m_scene = scene; - } - - - public override string Name - { - get { return "HGWorldMap"; } - } - - - #endregion - - /// - /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates - /// - /// - /// - /// - /// - public override void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) - { - // - // WARNING!!! COPY & PASTE FROM SUPERCLASS - // The only difference is at the very end - // - - m_log.Info("[HGMap]: Request map blocks " + minX + "-" + maxX + " " + minY + "-" + maxY); - - //m_scene.ForEachScenePresence(delegate (ScenePresence sp) { - // if (!sp.IsChildAgent && sp.UUID == remoteClient.AgentId) - // { - // Console.WriteLine("XXX Root agent"); - // DoRequestMapBlocks(remoteClient, minX, minY, maxX, maxY, flag); - // } - //}; - - List mapBlocks; - if ((flag & 0x10000) != 0) // user clicked on the map a tile that isn't visible - { - List response = new List(); - - // this should return one mapblock at most. But make sure: Look whether the one we requested is in there - mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); - if (mapBlocks != null) - { - foreach (MapBlockData block in mapBlocks) - { - if (block.X == minX && block.Y == minY) - { - // found it => add it to response - response.Add(block); - break; - } - } - } - response = mapBlocks; - if (response.Count == 0) - { - // response still empty => couldn't find the map-tile the user clicked on => tell the client - MapBlockData block = new MapBlockData(); - block.X = (ushort)minX; - block.Y = (ushort)minY; - block.Access = 254; // == not there - response.Add(block); - } - remoteClient.SendMapBlock(response, 0); - } - else - { - // normal mapblock request. Use the provided values - mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, maxX + 4, maxY + 4); - - // Different from super - FillInMap(mapBlocks, minX, minY, maxX, maxY); - // - - remoteClient.SendMapBlock(mapBlocks, flag); - } - } - - - private void FillInMap(List mapBlocks, int minX, int minY, int maxX, int maxY) - { - for (int x = minX; x <= maxX; x++) - for (int y = minY; y <= maxY; y++) - { - MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); }); - if (mblock == null) - { - mblock = new MapBlockData(); - mblock.X = (ushort)x; - mblock.Y = (ushort)y; - mblock.Name = ""; - mblock.Access = 254; // not here??? - mblock.MapImageId = UUID.Zero; - mapBlocks.Add(mblock); - } - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs deleted file mode 100644 index 12a76de8..0000000 --- a/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using System.Reflection; -using System.Threading; -using System.Web; - -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenMetaverse.Packets; - -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Capabilities; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -using OSD = OpenMetaverse.StructuredData.OSD; -using OSDMap = OpenMetaverse.StructuredData.OSDMap; -using OSDArray = OpenMetaverse.StructuredData.OSDArray; - -namespace OpenSim.Region.Environment.Modules.InterGrid -{ - public struct OGPState - { - public string first_name; - public string last_name; - public UUID agent_id; - public UUID local_agent_id; - public UUID region_id; - public uint circuit_code; - public UUID secure_session_id; - public UUID session_id; - public bool agent_access; - public string sim_access; - public uint god_level; - public bool god_overide; - public bool identified; - public bool transacted; - public bool age_verified; - public bool allow_redirect; - public int limited_to_estate; - public string inventory_host; - public bool src_can_see_mainland; - public int src_estate_id; - public int src_version; - public int src_parent_estate_id; - public bool visible_to_parent; - public string teleported_into_region; - } - - public class OpenGridProtocolModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private List m_scene = new List(); - - private Dictionary CapsLoginID = new Dictionary(); - private Dictionary m_OGPState = new Dictionary(); - private Dictionary m_loginToRegionState = new Dictionary(); - - - private string LastNameSuffix = "_EXTERNAL"; - private string FirstNamePrefix = ""; - private string httpsCN = ""; - private bool httpSSL = false; - private uint httpsslport = 0; - private bool GridMode = false; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - bool enabled = false; - IConfig cfg = null; - IConfig httpcfg = null; - IConfig startupcfg = null; - try - { - cfg = config.Configs["OpenGridProtocol"]; - } catch (NullReferenceException) - { - enabled = false; - } - - try - { - httpcfg = config.Configs["Network"]; - } - catch (NullReferenceException) - { - - } - try - { - startupcfg = config.Configs["Startup"]; - } - catch (NullReferenceException) - { - - } - - if (startupcfg != null) - { - GridMode = enabled = startupcfg.GetBoolean("gridmode", false); - } - - if (cfg != null) - { - enabled = cfg.GetBoolean("ogp_enabled", false); - LastNameSuffix = cfg.GetString("ogp_lastname_suffix", "_EXTERNAL"); - FirstNamePrefix = cfg.GetString("ogp_firstname_prefix", ""); - if (enabled) - { - m_log.Warn("[OGP]: Open Grid Protocol is on, Listening for Clients on /agent/"); - lock (m_scene) - { - if (m_scene.Count == 0) - { - scene.CommsManager.HttpServer.AddLLSDHandler("/agent/", ProcessAgentDomainMessage); - scene.CommsManager.HttpServer.AddLLSDHandler("/", ProcessRegionDomainSeed); - try - { - ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation; - } - catch (NotImplementedException) - { - try - { -#pragma warning disable 0612, 0618 - // Mono does not implement the ServicePointManager.ServerCertificateValidationCallback yet! Don't remove this! - ServicePointManager.CertificatePolicy = new MonoCert(); -#pragma warning restore 0612, 0618 - } - catch (Exception) - { - m_log.Error("[OGP]: Certificate validation handler change not supported. You may get ssl certificate validation errors teleporting from your region to some SSL regions."); - } - } - - } - // can't pick the region 'agent' because it would conflict with our agent domain handler - // a zero length region name would conflict with are base region seed cap - if (!SceneListDuplicateCheck(scene.RegionInfo.RegionName) && scene.RegionInfo.RegionName.ToLower() != "agent" && scene.RegionInfo.RegionName.Length > 0) - { - scene.CommsManager.HttpServer.AddLLSDHandler( - "/" + HttpUtility.UrlPathEncode(scene.RegionInfo.RegionName.ToLower()), - ProcessRegionDomainSeed); - } - - if (!m_scene.Contains(scene)) - m_scene.Add(scene); - } - } - } - lock (m_scene) - { - if (m_scene.Count == 1) - { - if (httpcfg != null) - { - httpSSL = httpcfg.GetBoolean("http_listener_ssl", false); - httpsCN = httpcfg.GetString("http_listener_cn", scene.RegionInfo.ExternalHostName); - if (httpsCN.Length == 0) - httpsCN = scene.RegionInfo.ExternalHostName; - httpsslport = (uint)httpcfg.GetInt("http_listener_sslport",((int)scene.RegionInfo.HttpPort + 1)); - } - } - } - } - - public void PostInitialise() - { - } - - public void Close() - { - //scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - } - - public string Name - { - get { return "OpenGridProtocolModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - public OSD ProcessRegionDomainSeed(string path, OSD request, string endpoint) - { - string[] pathSegments = path.Split('/'); - - if (pathSegments.Length <= 1) - { - return GenerateNoHandlerMessage(); - - } - - return GenerateRezAvatarRequestMessage(pathSegments[1]); - - - - //m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}", - // path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]); - //return new OSDMap(); - - } - - public OSD ProcessAgentDomainMessage(string path, OSD request, string endpoint) - { - // /agent/* - - string[] pathSegments = path.Split('/'); - if (pathSegments.Length <= 1) - { - return GenerateNoHandlerMessage(); - - } - if (pathSegments[0].Length == 0 && pathSegments[1].Length == 0) - { - return GenerateRezAvatarRequestMessage(""); - } - m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}", - path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]); - - switch (pathSegments[pathSegments.Length - 1]) - { - case "rez_avatar": - return RezAvatarMethod(path, request); - //break; - case "derez_avatar": - return DerezAvatarMethod(path, request); - //break; - - } - if (path.Length < 2) - { - return GenerateNoHandlerMessage(); - } - - switch (pathSegments[pathSegments.Length - 2] + "/" + pathSegments[pathSegments.Length - 1]) - { - case "rez_avatar/rez": - return RezAvatarMethod(path, request); - //break; - case "rez_avatar/request": - return RequestRezAvatarMethod(path, request); - case "rez_avatar/place": - return RequestRezAvatarMethod(path, request); - case "rez_avatar/derez": - return DerezAvatarMethod(path, request); - //break; - default: - return GenerateNoHandlerMessage(); - } - //return null; - } - - private OSD GenerateRezAvatarRequestMessage(string regionname) - { - Scene region = null; - bool usedroot = false; - - if (regionname.Length == 0) - { - region = GetRootScene(); - usedroot = true; - } - else - { - region = GetScene(HttpUtility.UrlDecode(regionname).ToLower()); - } - - // this shouldn't happen since we don't listen for a region that is down.. but - // it might if the region was taken down or is in the middle of restarting - - if (region == null) - { - region = GetRootScene(); - usedroot = true; - } - - UUID statekeeper = UUID.Random(); - - - - - RegionInfo reg = region.RegionInfo; - - OSDMap responseMap = new OSDMap(); - string rezHttpProtocol = "http://"; - //string regionCapsHttpProtocol = "http://"; - string httpaddr = reg.ExternalHostName; - string urlport = reg.HttpPort.ToString(); - string requestpath = "/agent/" + statekeeper + "/rez_avatar/request"; - - if (!usedroot) - { - lock (m_loginToRegionState) - { - if (!m_loginToRegionState.ContainsKey(requestpath)) - { - m_loginToRegionState.Add(requestpath, region.RegionInfo.RegionName.ToLower()); - } - } - } - - if (httpSSL) - { - rezHttpProtocol = "https://"; - //regionCapsHttpProtocol = "https://"; - urlport = httpsslport.ToString(); - - if (httpsCN.Length > 0) - httpaddr = httpsCN; - } - - responseMap["connect"] = OSD.FromBoolean(true); - OSDMap capabilitiesMap = new OSDMap(); - capabilitiesMap["rez_avatar/request"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + requestpath); - responseMap["capabilities"] = capabilitiesMap; - - return responseMap; - } - - // Using OpenSim.Framework.Communications.Capabilities.Caps here one time.. - // so the long name is probably better then a using statement - public void OnRegisterCaps(UUID agentID, OpenSim.Framework.Communications.Capabilities.Caps caps) - { - /* If we ever want to register our own caps here.... - * - string capsBase = "/CAPS/" + caps.CapsObjectPath; - caps.RegisterHandler("CAPNAME", - new RestStreamHandler("POST", capsBase + CAPSPOSTFIX!, - delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return METHODHANDLER(request, path, param, - agentID, caps); - })); - - * - */ - } - - public OSD RequestRezAvatarMethod(string path, OSD request) - { - //System.Console.WriteLine("[REQUESTREZAVATAR]: " + request.ToString()); - - OSDMap requestMap = (OSDMap)request; - - - Scene homeScene = null; - - lock (m_loginToRegionState) - { - if (m_loginToRegionState.ContainsKey(path)) - { - homeScene = GetScene(m_loginToRegionState[path]); - m_loginToRegionState.Remove(path); - - if (homeScene == null) - homeScene = GetRootScene(); - } - else - { - homeScene = GetRootScene(); - } - } - - // Homescene is still null, we must have no regions that are up - if (homeScene == null) - return GenerateNoHandlerMessage(); - - RegionInfo reg = homeScene.RegionInfo; - ulong regionhandle = GetOSCompatibleRegionHandle(reg); - //string RegionURI = reg.ServerURI; - //int RegionPort = (int)reg.HttpPort; - - UUID RemoteAgentID = requestMap["agent_id"].AsUUID(); - - // will be used in the future. The client always connects with the aditi agentid currently - UUID LocalAgentID = RemoteAgentID; - - string FirstName = requestMap["first_name"].AsString(); - string LastName = requestMap["last_name"].AsString(); - - FirstName = FirstNamePrefix + FirstName; - LastName = LastName + LastNameSuffix; - - OGPState userState = GetOGPState(LocalAgentID); - - userState.first_name = requestMap["first_name"].AsString(); - userState.last_name = requestMap["last_name"].AsString(); - userState.age_verified = requestMap["age_verified"].AsBoolean(); - userState.transacted = requestMap["transacted"].AsBoolean(); - userState.agent_access = requestMap["agent_access"].AsBoolean(); - userState.allow_redirect = requestMap["allow_redirect"].AsBoolean(); - userState.identified = requestMap["identified"].AsBoolean(); - userState.god_level = (uint)requestMap["god_level"].AsInteger(); - userState.sim_access = requestMap["sim_access"].AsString(); - userState.agent_id = RemoteAgentID; - userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger(); - userState.src_can_see_mainland = requestMap["src_can_see_mainland"].AsBoolean(); - userState.src_estate_id = requestMap["src_estate_id"].AsInteger(); - userState.local_agent_id = LocalAgentID; - userState.teleported_into_region = reg.RegionName.ToLower(); - - UpdateOGPState(LocalAgentID, userState); - - OSDMap responseMap = new OSDMap(); - - if (RemoteAgentID == UUID.Zero) - { - responseMap["connect"] = OSD.FromBoolean(false); - responseMap["message"] = OSD.FromString("No agent ID was specified in rez_avatar/request"); - m_log.Error("[OGP]: rez_avatar/request failed because no avatar UUID was provided in the request body"); - return responseMap; - } - - responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName); - - // DEPRECIATED - responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString()); - - responseMap["connect"] = OSD.FromBoolean(true); - responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port); - responseMap["region_x"] = OSD.FromInteger(reg.RegionLocX * (uint)Constants.RegionSize); // LLX - responseMap["region_y"] = OSD.FromInteger(reg.RegionLocY * (uint)Constants.RegionSize); // LLY - responseMap["region_id"] = OSD.FromUUID(reg.originRegionID); - responseMap["sim_access"] = OSD.FromString((reg.RegionSettings.Maturity == 1) ? "Mature" : "PG"); - - // Generate a dummy agent for the user so we can get back a CAPS path - AgentCircuitData agentData = new AgentCircuitData(); - agentData.AgentID = LocalAgentID; - agentData.BaseFolder = UUID.Zero; - agentData.CapsPath = CapsUtil.GetRandomCapsObjectPath(); - agentData.child = false; - agentData.circuitcode = (uint)(Util.RandomClass.Next()); - agentData.firstname = FirstName; - agentData.lastname = LastName; - agentData.SecureSessionID = UUID.Random(); - agentData.SessionID = UUID.Random(); - agentData.startpos = new Vector3(128f, 128f, 100f); - - // Pre-Fill our region cache with information on the agent. - UserAgentData useragent = new UserAgentData(); - useragent.AgentIP = "unknown"; - useragent.AgentOnline = true; - useragent.AgentPort = (uint)0; - useragent.Handle = regionhandle; - useragent.InitialRegion = reg.originRegionID; - useragent.LoginTime = Util.UnixTimeSinceEpoch(); - useragent.LogoutTime = 0; - useragent.Position = agentData.startpos; - useragent.Region = reg.originRegionID; - useragent.SecureSessionID = agentData.SecureSessionID; - useragent.SessionID = agentData.SessionID; - - UserProfileData userProfile = new UserProfileData(); - userProfile.AboutText = "OGP User"; - userProfile.CanDoMask = (uint)0; - userProfile.Created = Util.UnixTimeSinceEpoch(); - userProfile.CurrentAgent = useragent; - userProfile.CustomType = "OGP"; - userProfile.FirstLifeAboutText = "I'm testing OpenGrid Protocol"; - userProfile.FirstLifeImage = UUID.Zero; - userProfile.FirstName = agentData.firstname; - userProfile.GodLevel = 0; - userProfile.HomeLocation = agentData.startpos; - userProfile.HomeLocationX = agentData.startpos.X; - userProfile.HomeLocationY = agentData.startpos.Y; - userProfile.HomeLocationZ = agentData.startpos.Z; - userProfile.HomeLookAt = Vector3.Zero; - userProfile.HomeLookAtX = userProfile.HomeLookAt.X; - userProfile.HomeLookAtY = userProfile.HomeLookAt.Y; - userProfile.HomeLookAtZ = userProfile.HomeLookAt.Z; - userProfile.HomeRegion = reg.RegionHandle; - userProfile.HomeRegionID = reg.originRegionID; - userProfile.HomeRegionX = reg.RegionLocX; - userProfile.HomeRegionY = reg.RegionLocY; - userProfile.ID = agentData.AgentID; - userProfile.Image = UUID.Zero; - userProfile.LastLogin = Util.UnixTimeSinceEpoch(); - userProfile.Partner = UUID.Zero; - userProfile.PasswordHash = "$1$"; - userProfile.PasswordSalt = ""; - userProfile.RootInventoryFolderID = UUID.Zero; - userProfile.SurName = agentData.lastname; - userProfile.UserAssetURI = homeScene.CommsManager.NetworkServersInfo.AssetURL; - userProfile.UserFlags = 0; - userProfile.UserInventoryURI = homeScene.CommsManager.NetworkServersInfo.InventoryURL; - userProfile.WantDoMask = 0; - userProfile.WebLoginKey = UUID.Random(); - - // Do caps registration - // get seed capagentData.firstname = FirstName;agentData.lastname = LastName; - if (homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID) == null && !GridMode) - { - homeScene.CommsManager.UserAdminService.AddUser( - agentData.firstname, agentData.lastname, CreateRandomStr(7), "", - homeScene.RegionInfo.RegionLocX, homeScene.RegionInfo.RegionLocY, agentData.AgentID); - - UserProfileData userProfile2 = homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID); - if (userProfile2 != null) - { - userProfile = userProfile2; - userProfile.AboutText = "OGP USER"; - userProfile.FirstLifeAboutText = "OGP USER"; - homeScene.CommsManager.UserService.UpdateUserProfile(userProfile); - } - } - - // Stick our data in the cache so the region will know something about us - homeScene.CommsManager.UserProfileCacheService.PreloadUserCache(agentData.AgentID, userProfile); - - // Call 'new user' event handler - homeScene.NewUserConnection(agentData); - - //string raCap = string.Empty; - - UUID AvatarRezCapUUID = LocalAgentID; - string rezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/rez"; - string derezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/derez"; - // Get a reference to the user's cap so we can pull out the Caps Object Path - OpenSim.Framework.Communications.Capabilities.Caps userCap - = homeScene.CapsModule.GetCapsHandlerForUser(agentData.AgentID); - - string rezHttpProtocol = "http://"; - string regionCapsHttpProtocol = "http://"; - string httpaddr = reg.ExternalHostName; - string urlport = reg.HttpPort.ToString(); - - if (httpSSL) - { - rezHttpProtocol = "https://"; - regionCapsHttpProtocol = "https://"; - urlport = httpsslport.ToString(); - - if (httpsCN.Length > 0) - httpaddr = httpsCN; - } - - // DEPRECIATED - responseMap["seed_capability"] - = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); - - // REPLACEMENT - responseMap["region_seed_capability"] - = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); - - responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); - responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); - responseMap["rez_avatar/derez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + derezAvatarPath); - - // Add the user to the list of CAPS that are outstanding. - // well allow the caps hosts in this dictionary - lock (CapsLoginID) - { - if (CapsLoginID.ContainsKey(rezAvatarPath)) - { - CapsLoginID[rezAvatarPath] = agentData; - - // This is a joke, if you didn't notice... It's so unlikely to happen, that I'll print this message if it does occur! - m_log.Error("[OGP]: Holy anomoly batman! Caps path already existed! All the UUID Duplication worries were founded!"); - } - else - { - CapsLoginID.Add(rezAvatarPath, agentData); - } - } - - //System.Console.WriteLine("Response:" + responseMap.ToString()); - return responseMap; - } - - public OSD RezAvatarMethod(string path, OSD request) - { - m_log.WarnFormat("[REZAVATAR]: {0}", request.ToString()); - - OSDMap responseMap = new OSDMap(); - - AgentCircuitData userData = null; - - // Only people we've issued a cap can go further - if (TryGetAgentCircuitData(path,out userData)) - { - OSDMap requestMap = (OSDMap)request; - - // take these values to start. There's a few more - UUID SecureSessionID=requestMap["secure_session_id"].AsUUID(); - UUID SessionID = requestMap["session_id"].AsUUID(); - int circuitcode = requestMap["circuit_code"].AsInteger(); - OSDArray Parameter = new OSDArray(); - if (requestMap.ContainsKey("parameter")) - { - Parameter = (OSDArray)requestMap["parameter"]; - } - - //int version = 1; - int estateID = 1; - int parentEstateID = 1; - UUID regionID = UUID.Zero; - bool visibleToParent = true; - - for (int i = 0; i < Parameter.Count; i++) - { - OSDMap item = (OSDMap)Parameter[i]; -// if (item.ContainsKey("version")) -// { -// version = item["version"].AsInteger(); -// } - if (item.ContainsKey("estate_id")) - { - estateID = item["estate_id"].AsInteger(); - } - if (item.ContainsKey("parent_estate_id")) - { - parentEstateID = item["parent_estate_id"].AsInteger(); - - } - if (item.ContainsKey("region_id")) - { - regionID = item["region_id"].AsUUID(); - - } - if (item.ContainsKey("visible_to_parent")) - { - visibleToParent = item["visible_to_parent"].AsBoolean(); - } - } - //Update our Circuit data with the real values - userData.SecureSessionID = SecureSessionID; - userData.SessionID = SessionID; - - OGPState userState = GetOGPState(userData.AgentID); - - // Locate a home scene suitable for the user. - Scene homeScene = null; - - homeScene = GetScene(userState.teleported_into_region); - - if (homeScene == null) - homeScene = GetRootScene(); - - if (homeScene != null) - { - // Get a referenceokay - to their Cap object so we can pull out the capobjectroot - OpenSim.Framework.Communications.Capabilities.Caps userCap - = homeScene.CapsModule.GetCapsHandlerForUser(userData.AgentID); - - //Update the circuit data in the region so this user is authorized - homeScene.UpdateCircuitData(userData); - homeScene.ChangeCircuitCode(userData.circuitcode,(uint)circuitcode); - - // Load state - - - // Keep state changes - userState.first_name = requestMap["first_name"].AsString(); - userState.secure_session_id = requestMap["secure_session_id"].AsUUID(); - userState.age_verified = requestMap["age_verified"].AsBoolean(); - userState.region_id = homeScene.RegionInfo.originRegionID; // replace 0000000 with our regionid - userState.transacted = requestMap["transacted"].AsBoolean(); - userState.agent_access = requestMap["agent_access"].AsBoolean(); - userState.inventory_host = requestMap["inventory_host"].AsString(); - userState.identified = requestMap["identified"].AsBoolean(); - userState.session_id = requestMap["session_id"].AsUUID(); - userState.god_level = (uint)requestMap["god_level"].AsInteger(); - userState.last_name = requestMap["last_name"].AsString(); - userState.god_overide = requestMap["god_override"].AsBoolean(); - userState.circuit_code = (uint)requestMap["circuit_code"].AsInteger(); - userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger(); - userState.src_estate_id = estateID; - userState.region_id = regionID; - userState.src_parent_estate_id = parentEstateID; - userState.visible_to_parent = visibleToParent; - - // Save state changes - UpdateOGPState(userData.AgentID, userState); - - // Get the region information for the home region. - RegionInfo reg = homeScene.RegionInfo; - - // Dummy positional and look at info.. we don't have it. - OSDArray PositionArray = new OSDArray(); - PositionArray.Add(OSD.FromInteger(128)); - PositionArray.Add(OSD.FromInteger(128)); - PositionArray.Add(OSD.FromInteger(40)); - - OSDArray LookAtArray = new OSDArray(); - LookAtArray.Add(OSD.FromInteger(1)); - LookAtArray.Add(OSD.FromInteger(1)); - LookAtArray.Add(OSD.FromInteger(1)); - - // Our region's X and Y position in OpenSimulator space. - uint fooX = reg.RegionLocX; - uint fooY = reg.RegionLocY; - m_log.InfoFormat("[OGP]: region x({0}) region y({1})", fooX, fooY); - m_log.InfoFormat("[OGP]: region http {0} {1}", reg.ServerURI, reg.HttpPort); - m_log.InfoFormat("[OGO]: region UUID {0} ", reg.RegionID); - - // Convert the X and Y position to LL space - responseMap["region_x"] = OSD.FromInteger(fooX * (uint)Constants.RegionSize); // convert it to LL X - responseMap["region_y"] = OSD.FromInteger(fooY * (uint)Constants.RegionSize); // convert it to LL Y - - // Give em a new seed capability - responseMap["seed_capability"] = OSD.FromString("http://" + reg.ExternalHostName + ":" + reg.HttpPort + "/CAPS/" + userCap.CapsObjectPath + "0000/"); - responseMap["region"] = OSD.FromUUID(reg.originRegionID); - responseMap["look_at"] = LookAtArray; - - responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port); - responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName);// + ":" + reg.InternalEndPoint.Port.ToString()); - - // DEPRECIATED - responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString()); - - responseMap["session_id"] = OSD.FromUUID(SessionID); - responseMap["secure_session_id"] = OSD.FromUUID(SecureSessionID); - responseMap["circuit_code"] = OSD.FromInteger(circuitcode); - - responseMap["position"] = PositionArray; - - responseMap["region_id"] = OSD.FromUUID(reg.originRegionID); - - responseMap["sim_access"] = OSD.FromString("Mature"); - - responseMap["connect"] = OSD.FromBoolean(true); - - - - m_log.InfoFormat("[OGP]: host: {0}, IP {1}", responseMap["sim_host"].ToString(), responseMap["sim_ip"].ToString()); - } - } - - return responseMap; - } - - public OSD DerezAvatarMethod(string path, OSD request) - { - m_log.ErrorFormat("DerezPath: {0}, Request: {1}", path, request.ToString()); - - //LLSD llsdResponse = null; - OSDMap responseMap = new OSDMap(); - - string[] PathArray = path.Split('/'); - m_log.InfoFormat("[OGP]: prefix {0}, uuid {1}, suffix {2}", PathArray[1], PathArray[2], PathArray[3]); - string uuidString = PathArray[2]; - m_log.InfoFormat("[OGP]: Request to Derez avatar with UUID {0}", uuidString); - UUID userUUID = UUID.Zero; - if (UUID.TryParse(uuidString, out userUUID)) - { - UUID RemoteID = (UUID)uuidString; - UUID LocalID = RemoteID; - // FIXME: TODO: Routine to map RemoteUUIDs to LocalUUIds - // would be done already.. but the client connects with the Aditi UUID - // regardless over the UDP stack - - OGPState userState = GetOGPState(LocalID); - if (userState.agent_id != UUID.Zero) - { - //OSDMap outboundRequestMap = new OSDMap(); - OSDMap inboundRequestMap = (OSDMap)request; - string rezAvatarString = inboundRequestMap["rez_avatar"].AsString(); - if (rezAvatarString.Length == 0) - { - rezAvatarString = inboundRequestMap["rez_avatar/rez"].AsString(); - } - OSDArray LookAtArray = new OSDArray(); - LookAtArray.Add(OSD.FromInteger(1)); - LookAtArray.Add(OSD.FromInteger(1)); - LookAtArray.Add(OSD.FromInteger(1)); - - OSDArray PositionArray = new OSDArray(); - PositionArray.Add(OSD.FromInteger(128)); - PositionArray.Add(OSD.FromInteger(128)); - PositionArray.Add(OSD.FromInteger(40)); - - OSDArray lookArray = new OSDArray(); - lookArray.Add(OSD.FromInteger(128)); - lookArray.Add(OSD.FromInteger(128)); - lookArray.Add(OSD.FromInteger(40)); - - responseMap["connect"] = OSD.FromBoolean(true);// it's okay to give this user up - responseMap["look_at"] = LookAtArray; - - m_log.WarnFormat("[OGP]: Invoking rez_avatar on host:{0} for avatar: {1} {2}", rezAvatarString, userState.first_name, userState.last_name); - - OSDMap rezResponseMap = invokeRezAvatarCap(responseMap, rezAvatarString,userState); - - // If invoking it returned an error, parse and end - if (rezResponseMap.ContainsKey("connect")) - { - if (rezResponseMap["connect"].AsBoolean() == false) - { - return responseMap; - } - } - - string rezRespSeedCap = ""; - - // DEPRECIATED - if (rezResponseMap.ContainsKey("seed_capability")) - rezRespSeedCap = rezResponseMap["seed_capability"].AsString(); - - // REPLACEMENT - if (rezResponseMap.ContainsKey("region_seed_capability")) - rezRespSeedCap = rezResponseMap["region_seed_capability"].AsString(); - - // REPLACEMENT - if (rezResponseMap.ContainsKey("rez_avatar/rez")) - rezRespSeedCap = rezResponseMap["rez_avatar/rez"].AsString(); - - // DEPRECIATED - string rezRespSim_ip = rezResponseMap["sim_ip"].AsString(); - - string rezRespSim_host = rezResponseMap["sim_host"].AsString(); - - int rrPort = rezResponseMap["sim_port"].AsInteger(); - int rrX = rezResponseMap["region_x"].AsInteger(); - int rrY = rezResponseMap["region_y"].AsInteger(); - m_log.ErrorFormat("X:{0}, Y:{1}", rrX, rrY); - UUID rrRID = rezResponseMap["region_id"].AsUUID(); - OSDArray RezResponsePositionArray = null; - string rrAccess = rezResponseMap["sim_access"].AsString(); - if (rezResponseMap.ContainsKey("position")) - { - RezResponsePositionArray = (OSDArray)rezResponseMap["position"]; - } - // DEPRECIATED - responseMap["seed_capability"] = OSD.FromString(rezRespSeedCap); - - // REPLACEMENT r3 - responseMap["region_seed_capability"] = OSD.FromString(rezRespSeedCap); - - // DEPRECIATED - responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(rezRespSim_ip).ToString()); - - responseMap["sim_host"] = OSD.FromString(rezRespSim_host); - responseMap["sim_port"] = OSD.FromInteger(rrPort); - responseMap["region_x"] = OSD.FromInteger(rrX ); - responseMap["region_y"] = OSD.FromInteger(rrY ); - responseMap["region_id"] = OSD.FromUUID(rrRID); - responseMap["sim_access"] = OSD.FromString(rrAccess); - - if (RezResponsePositionArray != null) - { - responseMap["position"] = RezResponsePositionArray; - } - responseMap["look_at"] = lookArray; - responseMap["connect"] = OSD.FromBoolean(true); - - ShutdownConnection(LocalID,this); - // PLEASE STOP CHANGING THIS TO an M_LOG, M_LOG DOESN'T WORK ON MULTILINE .TOSTRINGS - System.Console.WriteLine("RESPONSEDEREZ: " + responseMap.ToString()); - return responseMap; - } - else - { - return GenerateNoStateMessage(LocalID); - } - } - else - { - return GenerateNoHandlerMessage(); - } - - //return responseMap; - } - - private OSDMap invokeRezAvatarCap(OSDMap responseMap, string CapAddress, OGPState userState) - { - Scene reg = GetRootScene(); - - WebRequest DeRezRequest = WebRequest.Create(CapAddress); - DeRezRequest.Method = "POST"; - DeRezRequest.ContentType = "application/xml+llsd"; - - OSDMap RAMap = new OSDMap(); - OSDMap AgentParms = new OSDMap(); - OSDMap RegionParms = new OSDMap(); - - OSDArray Parameter = new OSDArray(2); - - OSDMap version = new OSDMap(); - version["version"] = OSD.FromInteger(userState.src_version); - Parameter.Add(version); - - OSDMap SrcData = new OSDMap(); - SrcData["estate_id"] = OSD.FromInteger(reg.RegionInfo.EstateSettings.EstateID); - SrcData["parent_estate_id"] = OSD.FromInteger((reg.RegionInfo.EstateSettings.ParentEstateID == 100 ? 1 : reg.RegionInfo.EstateSettings.ParentEstateID)); - SrcData["region_id"] = OSD.FromUUID(reg.RegionInfo.originRegionID); - SrcData["visible_to_parent"] = OSD.FromBoolean(userState.visible_to_parent); - Parameter.Add(SrcData); - - AgentParms["first_name"] = OSD.FromString(userState.first_name); - AgentParms["last_name"] = OSD.FromString(userState.last_name); - AgentParms["agent_id"] = OSD.FromUUID(userState.agent_id); - RegionParms["region_id"] = OSD.FromUUID(userState.region_id); - AgentParms["circuit_code"] = OSD.FromInteger(userState.circuit_code); - AgentParms["secure_session_id"] = OSD.FromUUID(userState.secure_session_id); - AgentParms["session_id"] = OSD.FromUUID(userState.session_id); - AgentParms["agent_access"] = OSD.FromBoolean(userState.agent_access); - AgentParms["god_level"] = OSD.FromInteger(userState.god_level); - AgentParms["god_overide"] = OSD.FromBoolean(userState.god_overide); - AgentParms["identified"] = OSD.FromBoolean(userState.identified); - AgentParms["transacted"] = OSD.FromBoolean(userState.transacted); - AgentParms["age_verified"] = OSD.FromBoolean(userState.age_verified); - AgentParms["limited_to_estate"] = OSD.FromInteger(userState.limited_to_estate); - AgentParms["inventory_host"] = OSD.FromString(userState.inventory_host); - - // version 1 - RAMap = AgentParms; - - // Planned for version 2 - // RAMap["agent_params"] = AgentParms; - - RAMap["region_params"] = RegionParms; - RAMap["parameter"] = Parameter; - - string RAMapString = RAMap.ToString(); - m_log.InfoFormat("[OGP] RAMap string {0}", RAMapString); - OSD LLSDofRAMap = RAMap; // RENAME if this works - - m_log.InfoFormat("[OGP]: LLSD of map as string was {0}", LLSDofRAMap.ToString()); - //m_log.InfoFormat("[OGP]: LLSD+XML: {0}", LLSDParser.SerializeXmlString(LLSDofRAMap)); - byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); - - //string bufferDump = System.Text.Encoding.ASCII.GetString(buffer); - //m_log.InfoFormat("[OGP]: buffer form is {0}",bufferDump); - //m_log.InfoFormat("[OGP]: LLSD of map was {0}",buffer.Length); - - Stream os = null; - try - { // send the Post - DeRezRequest.ContentLength = buffer.Length; //Count bytes to send - os = DeRezRequest.GetRequestStream(); - os.Write(buffer, 0, buffer.Length); //Send it - os.Close(); - m_log.InfoFormat("[OGP]: Derez Avatar Posted Rez Avatar request to remote sim {0}", CapAddress); - } - catch (WebException ex) - { - m_log.InfoFormat("[OGP] Bad send on de_rez_avatar {0}", ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); - - return responseMap; - } - - m_log.Info("[OGP] waiting for a reply after rez avatar send"); - string rez_avatar_reply = null; - { // get the response - try - { - WebResponse webResponse = DeRezRequest.GetResponse(); - if (webResponse == null) - { - m_log.Info("[OGP:] Null reply on rez_avatar post"); - } - - StreamReader sr = new StreamReader(webResponse.GetResponseStream()); - rez_avatar_reply = sr.ReadToEnd().Trim(); - m_log.InfoFormat("[OGP]: rez_avatar reply was {0} ", rez_avatar_reply); - - } - catch (WebException ex) - { - m_log.InfoFormat("[OGP]: exception on read after send of rez avatar {0}", ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); - - return responseMap; - } - OSD rezResponse = null; - try - { - rezResponse = OSDParser.DeserializeLLSDXml(rez_avatar_reply); - - responseMap = (OSDMap)rezResponse; - } - catch (Exception ex) - { - m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); - - return responseMap; - } - } - return responseMap; - } - - public OSD GenerateNoHandlerMessage() - { - OSDMap map = new OSDMap(); - map["reason"] = OSD.FromString("LLSDRequest"); - map["message"] = OSD.FromString("No handler registered for LLSD Requests"); - map["login"] = OSD.FromString("false"); - map["connect"] = OSD.FromString("false"); - return map; - } - public OSD GenerateNoStateMessage(UUID passedAvatar) - { - OSDMap map = new OSDMap(); - map["reason"] = OSD.FromString("derez failed"); - map["message"] = OSD.FromString("Unable to locate OGP state for avatar " + passedAvatar.ToString()); - map["login"] = OSD.FromString("false"); - map["connect"] = OSD.FromString("false"); - return map; - } - private bool TryGetAgentCircuitData(string path, out AgentCircuitData userdata) - { - userdata = null; - lock (CapsLoginID) - { - if (CapsLoginID.ContainsKey(path)) - { - userdata = CapsLoginID[path]; - DiscardUsedCap(path); - return true; - } - } - return false; - } - - private void DiscardUsedCap(string path) - { - CapsLoginID.Remove(path); - } - - private Scene GetRootScene() - { - Scene ReturnScene = null; - lock (m_scene) - { - if (m_scene.Count > 0) - { - ReturnScene = m_scene[0]; - } - } - - return ReturnScene; - } - - private Scene GetScene(string scenename) - { - Scene ReturnScene = null; - lock (m_scene) - { - foreach (Scene s in m_scene) - { - if (s.RegionInfo.RegionName.ToLower() == scenename) - { - ReturnScene = s; - break; - } - } - } - - return ReturnScene; - } - - private ulong GetOSCompatibleRegionHandle(RegionInfo reg) - { - return Util.UIntsToLong(reg.RegionLocX, reg.RegionLocY); - } - - private OGPState InitializeNewState() - { - OGPState returnState = new OGPState(); - returnState.first_name = ""; - returnState.last_name = ""; - returnState.agent_id = UUID.Zero; - returnState.local_agent_id = UUID.Zero; - returnState.region_id = UUID.Zero; - returnState.circuit_code = 0; - returnState.secure_session_id = UUID.Zero; - returnState.session_id = UUID.Zero; - returnState.agent_access = true; - returnState.god_level = 0; - returnState.god_overide = false; - returnState.identified = false; - returnState.transacted = false; - returnState.age_verified = false; - returnState.limited_to_estate = 1; - returnState.inventory_host = "http://inv4.mysql.aditi.lindenlab.com"; - returnState.allow_redirect = true; - returnState.sim_access = ""; - returnState.src_can_see_mainland = true; - returnState.src_estate_id = 1; - returnState.src_version = 1; - returnState.src_parent_estate_id = 1; - returnState.visible_to_parent = true; - returnState.teleported_into_region = ""; - - return returnState; - } - - private OGPState GetOGPState(UUID agentId) - { - lock (m_OGPState) - { - if (m_OGPState.ContainsKey(agentId)) - { - return m_OGPState[agentId]; - } - else - { - return InitializeNewState(); - } - } - } - - public void DeleteOGPState(UUID agentId) - { - lock (m_OGPState) - { - if (m_OGPState.ContainsKey(agentId)) - m_OGPState.Remove(agentId); - } - } - - private void UpdateOGPState(UUID agentId, OGPState state) - { - lock (m_OGPState) - { - if (m_OGPState.ContainsKey(agentId)) - { - m_OGPState[agentId] = state; - } - else - { - m_OGPState.Add(agentId,state); - } - } - } - private bool SceneListDuplicateCheck(string str) - { - // no lock, called from locked space! - bool found = false; - - foreach (Scene s in m_scene) - { - if (s.RegionInfo.RegionName == str) - { - found = true; - break; - } - } - - return found; - } - - public void ShutdownConnection(UUID avatarId, OpenGridProtocolModule mod) - { - Scene homeScene = GetRootScene(); - ScenePresence avatar = null; - if (homeScene.TryGetAvatar(avatarId,out avatar)) - { - KillAUser ku = new KillAUser(avatar,mod); - Thread ta = new Thread(ku.ShutdownNoLogout); - ta.IsBackground = true; - ta.Name = "ShutdownThread"; - ta.Start(); - } - } - - private string CreateRandomStr(int len) - { - Random rnd = new Random(System.Environment.TickCount); - string returnstring = ""; - string chars = "abcdefghijklmnopqrstuvwxyz0123456789"; - - for (int i = 0; i < len; i++) - { - returnstring += chars.Substring(rnd.Next(chars.Length), 1); - } - return returnstring; - } - // Temporary hack to allow teleporting to and from Vaak - private static bool customXertificateValidation(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) - { - //if (cert.Subject == "E=root@lindenlab.com, CN=*.vaak.lindenlab.com, O=\"Linden Lab, Inc.\", L=San Francisco, S=California, C=US") - //{ - return true; - //} - - //return false; - } - } - - public class KillAUser - { - private ScenePresence avToBeKilled = null; - private OpenGridProtocolModule m_mod = null; - - public KillAUser(ScenePresence avatar, OpenGridProtocolModule mod) - { - avToBeKilled = avatar; - m_mod = mod; - } - - public void ShutdownNoLogout() - { - UUID avUUID = UUID.Zero; - - if (avToBeKilled != null) - { - avUUID = avToBeKilled.UUID; - avToBeKilled.MakeChildAgent(); - - avToBeKilled.ControllingClient.SendLogoutPacketWhenClosing = false; - - Thread.Sleep(30000); - - // test for child agent because they might have come back - if (avToBeKilled.IsChildAgent) - { - m_mod.DeleteOGPState(avUUID); - avToBeKilled.ControllingClient.Close(true); - } - } - } - - } - - public class MonoCert : ICertificatePolicy - { - #region ICertificatePolicy Members - - public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) - { - return true; - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs deleted file mode 100644 index f498f9a..0000000 --- a/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using OpenMetaverse; -using OpenMetaverse.Imaging; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Scripting.DynamicTexture -{ - public class DynamicTextureModule : IRegionModule, IDynamicTextureManager - { - private Dictionary RegisteredScenes = new Dictionary(); - - private Dictionary RenderPlugins = - new Dictionary(); - - private Dictionary Updaters = new Dictionary(); - - #region IDynamicTextureManager Members - - public void RegisterRender(string handleType, IDynamicTextureRender render) - { - if (!RenderPlugins.ContainsKey(handleType)) - { - RenderPlugins.Add(handleType, render); - } - } - - /// - /// Called by code which actually renders the dynamic texture to supply texture data. - /// - /// - /// - public void ReturnData(UUID id, byte[] data) - { - if (Updaters.ContainsKey(id)) - { - DynamicTextureUpdater updater = Updaters[id]; - if (RegisteredScenes.ContainsKey(updater.SimUUID)) - { - Scene scene = RegisteredScenes[updater.SimUUID]; - updater.DataReceived(data, scene); - } - } - } - - public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer) - { - return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); - } - - public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) - { - if (RenderPlugins.ContainsKey(contentType)) - { - //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType); - - DynamicTextureUpdater updater = new DynamicTextureUpdater(); - updater.SimUUID = simID; - updater.PrimID = primID; - updater.ContentType = contentType; - updater.Url = url; - updater.UpdateTimer = updateTimer; - updater.UpdaterID = UUID.Random(); - updater.Params = extraParams; - updater.BlendWithOldTexture = SetBlending; - updater.FrontAlpha = AlphaValue; - - if (!Updaters.ContainsKey(updater.UpdaterID)) - { - Updaters.Add(updater.UpdaterID, updater); - } - - RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); - return updater.UpdaterID; - } - return UUID.Zero; - } - - public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer) - { - return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); - } - - public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) - { - if (RenderPlugins.ContainsKey(contentType)) - { - DynamicTextureUpdater updater = new DynamicTextureUpdater(); - updater.SimUUID = simID; - updater.PrimID = primID; - updater.ContentType = contentType; - updater.BodyData = data; - updater.UpdateTimer = updateTimer; - updater.UpdaterID = UUID.Random(); - updater.Params = extraParams; - updater.BlendWithOldTexture = SetBlending; - updater.FrontAlpha = AlphaValue; - - if (!Updaters.ContainsKey(updater.UpdaterID)) - { - Updaters.Add(updater.UpdaterID, updater); - } - - RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); - return updater.UpdaterID; - } - return UUID.Zero; - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) - { - RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); - scene.RegisterModuleInterface(this); - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "DynamicTextureModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region Nested type: DynamicTextureUpdater - - public class DynamicTextureUpdater - { - public bool BlendWithOldTexture = false; - public string BodyData; - public string ContentType; - public byte FrontAlpha = 255; - public UUID LastAssetID; - public string Params; - public UUID PrimID; - public bool SetNewFrontAlpha = false; - public UUID SimUUID; - public UUID UpdaterID; - public int UpdateTimer; - public string Url; - - public DynamicTextureUpdater() - { - LastAssetID = UUID.Zero; - UpdateTimer = 0; - BodyData = null; - } - - /// - /// Called once new texture data has been received for this updater. - /// - public void DataReceived(byte[] data, Scene scene) - { - SceneObjectPart part = scene.GetSceneObjectPart(PrimID); - byte[] assetData; - AssetBase oldAsset = null; - - if (BlendWithOldTexture) - { - UUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID; - oldAsset = scene.AssetCache.GetAsset(lastTextureID, true); - if (oldAsset != null) - { - assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); - } - else - { - assetData = new byte[data.Length]; - Array.Copy(data, assetData, data.Length); - } - } - else - { - assetData = new byte[data.Length]; - Array.Copy(data, assetData, data.Length); - } - - // Create a new asset for user - AssetBase asset = new AssetBase(); - asset.Metadata.FullID = UUID.Random(); - asset.Data = assetData; - asset.Metadata.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); - asset.Metadata.Type = 0; - asset.Metadata.Description = "dynamic image"; - asset.Metadata.Local = false; - asset.Metadata.Temporary = true; - scene.AssetCache.AddAsset(asset); - - LastAssetID = asset.Metadata.FullID; - - IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface(); - if (cacheLayerDecode != null) - { - cacheLayerDecode.syncdecode(asset.Metadata.FullID, asset.Data); - } - cacheLayerDecode = null; - - // mostly keep the values from before - Primitive.TextureEntry tmptex = part.Shape.Textures; - - // remove the old asset from the cache - UUID oldID = tmptex.DefaultTexture.TextureID; - scene.AssetCache.ExpireAsset(oldID); - - tmptex.DefaultTexture.TextureID = asset.Metadata.FullID; - // I'm pretty sure we always want to force this to true - tmptex.DefaultTexture.Fullbright = true; - - part.Shape.Textures = tmptex; - part.ScheduleFullUpdate(); - } - - private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) - { - ManagedImage managedImage; - Image image; - - if (OpenJPEG.DecodeToImage(frontImage, out managedImage, out image)) - { - Bitmap image1 = new Bitmap(image); - - if (OpenJPEG.DecodeToImage(backImage, out managedImage, out image)) - { - Bitmap image2 = new Bitmap(image); - - if (setNewAlpha) - SetAlpha(ref image1, newAlpha); - - Bitmap joint = MergeBitMaps(image1, image2); - - byte[] result = new byte[0]; - - try - { - result = OpenJPEG.EncodeFromImage(joint, true); - } - catch (Exception) - { - Console.WriteLine( - "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); - } - - return result; - } - } - - return null; - } - - public Bitmap MergeBitMaps(Bitmap front, Bitmap back) - { - Bitmap joint; - Graphics jG; - - joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb); - jG = Graphics.FromImage(joint); - - jG.DrawImage(back, 0, 0, back.Width, back.Height); - jG.DrawImage(front, 0, 0, back.Width, back.Height); - - return joint; - } - - private void SetAlpha(ref Bitmap b, byte alpha) - { - for (int w = 0; w < b.Width; w++) - { - for (int h = 0; h < b.Height; h++) - { - b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h))); - } - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs deleted file mode 100644 index 81ce761..0000000 --- a/OpenSim/Region/Environment/Modules/Scripting/EMailModules/EmailModule.cs +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using log4net; -using Nini.Config; -using DotNetOpenMail; -using DotNetOpenMail.SmtpAuth; - -namespace OpenSim.Region.Environment.Modules.Scripting.EmailModules -{ - public class EmailModule : IEmailModule - { - // - // Log - // - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // - // Module vars - // - private IConfigSource m_Config; - private string m_HostName = string.Empty; - //private string m_RegionName = string.Empty; - private string SMTP_SERVER_HOSTNAME = string.Empty; - private int SMTP_SERVER_PORT = 25; - private string SMTP_SERVER_LOGIN = string.Empty; - private string SMTP_SERVER_PASSWORD = string.Empty; - - // Scenes by Region Handle - private Dictionary m_Scenes = - new Dictionary(); - - private bool m_Enabled = false; - - public void Initialise(Scene scene, IConfigSource config) - { - m_Config = config; - IConfig SMTPConfig; - - //FIXME: RegionName is correct?? - //m_RegionName = scene.RegionInfo.RegionName; - - IConfig startupConfig = m_Config.Configs["Startup"]; - - m_Enabled = (startupConfig.GetString("emailmodule", "DefaultEmailModule") == "DefaultEmailModule"); - - //Load SMTP SERVER config - try - { - if ((SMTPConfig = m_Config.Configs["SMTP"]) == null) - { - m_log.InfoFormat("[SMTP] SMTP server not configured"); - m_Enabled = false; - return; - } - - if (!SMTPConfig.GetBoolean("enabled", false)) - { - m_log.InfoFormat("[SMTP] module disabled in configuration"); - m_Enabled = false; - return; - } - - m_HostName = SMTPConfig.GetString("host_domain_header_from", m_HostName); - SMTP_SERVER_HOSTNAME = SMTPConfig.GetString("SMTP_SERVER_HOSTNAME",SMTP_SERVER_HOSTNAME); - SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT); - SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN); - SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD); - } - catch (Exception e) - { - m_log.Error("[EMAIL] DefaultEmailModule not configured: "+ e.Message); - m_Enabled = false; - return; - } - - // It's a go! - if (m_Enabled) - { - lock (m_Scenes) - { - // Claim the interface slot - scene.RegisterModuleInterface(this); - - // Add to scene list - if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle)) - { - m_Scenes[scene.RegionInfo.RegionHandle] = scene; - } - else - { - m_Scenes.Add(scene.RegionInfo.RegionHandle, scene); - } - } - - m_log.Info("[EMAIL] Activated DefaultEmailModule"); - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "DefaultEmailModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - /// - /// - /// - /// - private void DelayInSeconds(int seconds) - { - TimeSpan DiffDelay = new TimeSpan(0, 0, seconds); - DateTime EndDelay = DateTime.Now.Add(DiffDelay); - while (DateTime.Now < EndDelay) - { - ;//Do nothing!! - } - } - - private SceneObjectPart findPrim(UUID objectID, out string ObjectRegionName) - { - lock (m_Scenes) - { - foreach (Scene s in m_Scenes.Values) - { - SceneObjectPart part = s.GetSceneObjectPart(objectID); - if (part != null) - { - ObjectRegionName = s.RegionInfo.RegionName; - return part; - } - } - } - ObjectRegionName = string.Empty; - return null; - } - - private void resolveNamePositionRegionName(UUID objectID, out string ObjectName, out string ObjectAbsolutePosition, out string ObjectRegionName) - { - string m_ObjectRegionName; - SceneObjectPart part = findPrim(objectID, out m_ObjectRegionName); - if (part != null) - { - ObjectAbsolutePosition = part.AbsolutePosition.ToString(); - ObjectName = part.Name; - ObjectRegionName = m_ObjectRegionName; - return; - } - ObjectAbsolutePosition = part.AbsolutePosition.ToString(); - ObjectName = part.Name; - ObjectRegionName = m_ObjectRegionName; - return; - } - - /// - /// SendMail function utilized by llEMail - /// - /// - /// - /// - /// - public void SendEmail(UUID objectID, string address, string subject, string body) - { - //Check if address is empty - if (address == string.Empty) - return; - - //FIXED:Check the email is correct form in REGEX - string EMailpatternStrict = @"^(([^<>()[\]\\.,;:\s@\""]+" - + @"(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@" - + @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" - + @"\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+" - + @"[a-zA-Z]{2,}))$"; - Regex EMailreStrict = new Regex(EMailpatternStrict); - bool isEMailStrictMatch = EMailreStrict.IsMatch(address); - if (!isEMailStrictMatch) - { - m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); - return; - } - //FIXME:Check if subject + body = 4096 Byte - if ((subject.Length + body.Length) > 1024) - { - m_log.Error("[EMAIL] subject + body > 1024 Byte"); - return; - } - - try - { - string LastObjectName = string.Empty; - string LastObjectPosition = string.Empty; - string LastObjectRegionName = string.Empty; - //DONE: Message as Second Life style - //20 second delay - AntiSpam System - for now only 10 seconds - DelayInSeconds(10); - //Creation EmailMessage - EmailMessage emailMessage = new EmailMessage(); - //From - emailMessage.FromAddress = new EmailAddress(objectID.ToString()+"@"+m_HostName); - //To - Only One - emailMessage.AddToAddress(new EmailAddress(address)); - //Subject - emailMessage.Subject = subject; - //TEXT Body - resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); - emailMessage.TextPart = new TextAttachment("Object-Name: " + LastObjectName + - "\r\nRegion: " + LastObjectRegionName + "\r\nLocal-Position: " + - LastObjectPosition+"\r\n\r\n\r\n" + body); - //HTML Body - emailMessage.HtmlPart = new HtmlAttachment("

" + - "
Object-Name: " + LastObjectName + - "
Region: " + LastObjectRegionName + - "
Local-Position: " + LastObjectPosition + "


" - +body+"\r\n

"); - - //Set SMTP SERVER config - SmtpServer smtpServer=new SmtpServer(SMTP_SERVER_HOSTNAME,SMTP_SERVER_PORT); - //Authentication - smtpServer.SmtpAuthToken=new SmtpAuthToken(SMTP_SERVER_LOGIN, SMTP_SERVER_PASSWORD); - //Send Email Message - emailMessage.Send(smtpServer); - //Log - m_log.Info("[EMAIL] EMail sent to: " + address + " from object: " + objectID.ToString()); - } - catch (Exception e) - { - m_log.Error("[EMAIL] DefaultEmailModule Exception: "+e.Message); - return; - } - } - - /// - /// - /// - /// - /// - /// - /// - public Email GetNextEmail(UUID objectID, string sender, string subject) - { - return null; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs deleted file mode 100644 index faa6f3c..0000000 --- a/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using System.Threading; -using OpenMetaverse; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using System.Collections; - -/***************************************************** - * - * ScriptsHttpRequests - * - * Implements the llHttpRequest and http_response - * callback. - * - * Some stuff was already in LSLLongCmdHandler, and then - * there was this file with a stub class in it. So, - * I am moving some of the objects and functions out of - * LSLLongCmdHandler, such as the HttpRequestClass, the - * start and stop methods, and setting up pending and - * completed queues. These are processed in the - * LSLLongCmdHandler polling loop. Similiar to the - * XMLRPCModule, since that seems to work. - * - * //TODO - * - * This probably needs some throttling mechanism but - * it's wide open right now. This applies to both - * number of requests and data volume. - * - * Linden puts all kinds of header fields in the requests. - * Not doing any of that: - * User-Agent - * X-SecondLife-Shard - * X-SecondLife-Object-Name - * X-SecondLife-Object-Key - * X-SecondLife-Region - * X-SecondLife-Local-Position - * X-SecondLife-Local-Velocity - * X-SecondLife-Local-Rotation - * X-SecondLife-Owner-Name - * X-SecondLife-Owner-Key - * - * HTTPS support - * - * Configurable timeout? - * Configurable max response size? - * Configurable - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest -{ - public class HttpRequestModule : IRegionModule, IHttpRequestModule - { - private object HttpListLock = new object(); - private int httpTimeout = 30000; - private string m_name = "HttpScriptRequests"; - - private string m_proxyurl = ""; - private string m_proxyexcepts = ""; - - // - private Dictionary m_pendingRequests; - private Scene m_scene; - // private Queue rpcQueue = new Queue(); - - public HttpRequestModule() - { - } - - #region IHttpRequestModule Members - - public UUID MakeHttpRequest(string url, string parameters, string body) - { - return UUID.Zero; - } - - public UUID StartHttpRequest(uint localID, UUID itemID, string url, List parameters, Dictionary headers, string body) - { - UUID reqID = UUID.Random(); - HttpRequestClass htc = new HttpRequestClass(); - - // Partial implementation: support for parameter flags needed - // see http://wiki.secondlife.com/wiki/LlHTTPRequest - // - // Parameters are expected in {key, value, ... , key, value} - if (parameters != null) - { - string[] parms = parameters.ToArray(); - for (int i = 0; i < parms.Length; i += 2) - { - switch (Int32.Parse(parms[i])) - { - case (int)HttpRequestConstants.HTTP_METHOD: - - htc.HttpMethod = parms[i + 1]; - break; - - case (int)HttpRequestConstants.HTTP_MIMETYPE: - - htc.HttpMIMEType = parms[i + 1]; - break; - - case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH: - - // TODO implement me - break; - - case (int)HttpRequestConstants.HTTP_VERIFY_CERT: - - // TODO implement me - break; - } - } - } - - htc.LocalID = localID; - htc.ItemID = itemID; - htc.Url = url; - htc.ReqID = reqID; - htc.HttpTimeout = httpTimeout; - htc.OutboundBody = body; - htc.ResponseHeaders = headers; - htc.proxyurl = m_proxyurl; - htc.proxyexcepts = m_proxyexcepts; - - lock (HttpListLock) - { - m_pendingRequests.Add(reqID, htc); - } - - htc.Process(); - - return reqID; - } - - public void StopHttpRequest(uint m_localID, UUID m_itemID) - { - if (m_pendingRequests != null) - { - lock (HttpListLock) - { - HttpRequestClass tmpReq; - if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) - { - tmpReq.Stop(); - m_pendingRequests.Remove(m_itemID); - } - } - } - } - - /* - * TODO - * Not sure how important ordering is is here - the next first - * one completed in the list is returned, based soley on its list - * position, not the order in which the request was started or - * finsihed. I thought about setting up a queue for this, but - * it will need some refactoring and this works 'enough' right now - */ - - public IServiceRequest GetNextCompletedRequest() - { - lock (HttpListLock) - { - foreach (UUID luid in m_pendingRequests.Keys) - { - HttpRequestClass tmpReq; - - if (m_pendingRequests.TryGetValue(luid, out tmpReq)) - { - if (tmpReq.Finished) - { - return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedRequest(UUID id) - { - lock (HttpListLock) - { - HttpRequestClass tmpReq; - if (m_pendingRequests.TryGetValue(id, out tmpReq)) - { - tmpReq.Stop(); - tmpReq = null; - m_pendingRequests.Remove(id); - } - } - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - - m_scene.RegisterModuleInterface(this); - - m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); - m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); - - m_pendingRequests = new Dictionary(); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - } - - public class HttpRequestClass: IServiceRequest - { - // Constants for parameters - // public const int HTTP_BODY_MAXLENGTH = 2; - // public const int HTTP_METHOD = 0; - // public const int HTTP_MIMETYPE = 1; - // public const int HTTP_VERIFY_CERT = 3; - private bool _finished; - public bool Finished - { - get { return _finished; } - } - // public int HttpBodyMaxLen = 2048; // not implemented - - // Parameter members and default values - public string HttpMethod = "GET"; - public string HttpMIMEType = "text/plain;charset=utf-8"; - public int HttpTimeout; - // public bool HttpVerifyCert = true; // not implemented - private Thread httpThread; - - // Request info - private UUID _itemID; - public UUID ItemID - { - get { return _itemID; } - set { _itemID = value; } - } - private uint _localID; - public uint LocalID - { - get { return _localID; } - set { _localID = value; } - } - public DateTime Next; - public string proxyurl; - public string proxyexcepts; - public string OutboundBody; - private UUID _reqID; - public UUID ReqID - { - get { return _reqID; } - set { _reqID = value; } - } - public HttpWebRequest Request; - public string ResponseBody; - public List ResponseMetadata; - public Dictionary ResponseHeaders; - public int Status; - public string Url; - - public void Process() - { - httpThread = new Thread(SendRequest); - httpThread.Name = "HttpRequestThread"; - httpThread.Priority = ThreadPriority.BelowNormal; - httpThread.IsBackground = true; - _finished = false; - httpThread.Start(); - ThreadTracker.Add(httpThread); - } - - /* - * TODO: More work on the response codes. Right now - * returning 200 for success or 499 for exception - */ - - public void SendRequest() - { - HttpWebResponse response = null; - StringBuilder sb = new StringBuilder(); - byte[] buf = new byte[8192]; - string tempString = null; - int count = 0; - - try - { - Request = (HttpWebRequest) WebRequest.Create(Url); - Request.Method = HttpMethod; - Request.ContentType = HttpMIMEType; - - if (proxyurl != null && proxyurl.Length > 0) - { - if (proxyexcepts != null && proxyexcepts.Length > 0) - { - string[] elist = proxyexcepts.Split(';'); - Request.Proxy = new WebProxy(proxyurl, true, elist); - } - else - { - Request.Proxy = new WebProxy(proxyurl, true); - } - } - - foreach (KeyValuePair entry in ResponseHeaders) - Request.Headers[entry.Key] = entry.Value; - - // Encode outbound data - if (OutboundBody.Length > 0) - { - byte[] data = Encoding.UTF8.GetBytes(OutboundBody); - - Request.ContentLength = data.Length; - Stream bstream = Request.GetRequestStream(); - bstream.Write(data, 0, data.Length); - bstream.Close(); - } - - Request.Timeout = HttpTimeout; - // execute the request - response = (HttpWebResponse) Request.GetResponse(); - - Stream resStream = response.GetResponseStream(); - - do - { - // fill the buffer with data - count = resStream.Read(buf, 0, buf.Length); - - // make sure we read some data - if (count != 0) - { - // translate from bytes to ASCII text - tempString = Encoding.UTF8.GetString(buf, 0, count); - - // continue building the string - sb.Append(tempString); - } - } while (count > 0); // any more data to read? - - ResponseBody = sb.ToString(); - } - catch (Exception e) - { - if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError) - { - HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; - Status = (int)webRsp.StatusCode; - ResponseBody = webRsp.StatusDescription; - } - else - { - Status = (int)OSHttpStatusCode.ClientErrorJoker; - ResponseBody = e.Message; - } - - _finished = true; - return; - } - finally - { - if (response != null) - response.Close(); - } - - Status = (int)OSHttpStatusCode.SuccessOk; - _finished = true; - } - - public void Stop() - { - try - { - httpThread.Abort(); - } - catch (Exception) - { - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs deleted file mode 100644 index 0112ee6..0000000 --- a/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Drawing; -using System.IO; -using System.Net; -using OpenMetaverse; -using OpenMetaverse.Imaging; -using Nini.Config; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Scripting.LoadImageURL -{ - public class LoadImageURLModule : IRegionModule, IDynamicTextureRender - { - private string m_name = "LoadImageURL"; - private Scene m_scene; - private IDynamicTextureManager m_textureManager; - - private string m_proxyurl = ""; - private string m_proxyexcepts = ""; - - #region IDynamicTextureRender Members - - public string GetName() - { - return m_name; - } - - public string GetContentType() - { - return ("image"); - } - - public bool SupportsAsynchronous() - { - return true; - } - - public byte[] ConvertUrl(string url, string extraParams) - { - return null; - } - - public byte[] ConvertStream(Stream data, string extraParams) - { - return null; - } - - public bool AsyncConvertUrl(UUID id, string url, string extraParams) - { - MakeHttpRequest(url, id); - return true; - } - - public bool AsyncConvertData(UUID id, string bodyData, string extraParams) - { - return false; - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (m_scene == null) - { - m_scene = scene; - } - - m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); - m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); - } - - public void PostInitialise() - { - m_textureManager = m_scene.RequestModuleInterface(); - if (m_textureManager != null) - { - m_textureManager.RegisterRender(GetContentType(), this); - } - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void MakeHttpRequest(string url, UUID requestID) - { - WebRequest request = HttpWebRequest.Create(url); - - if (m_proxyurl != null && m_proxyurl.Length > 0) - { - if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) - { - string[] elist = m_proxyexcepts.Split(';'); - request.Proxy = new WebProxy(m_proxyurl, true, elist); - } - else - { - request.Proxy = new WebProxy(m_proxyurl, true); - } - } - - RequestState state = new RequestState((HttpWebRequest) request, requestID); - // IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); - request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); - - TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1)); - state.TimeOfRequest = (int) t.TotalSeconds; - } - - private void HttpRequestReturn(IAsyncResult result) - { - RequestState state = (RequestState) result.AsyncState; - WebRequest request = (WebRequest) state.Request; - try - { - HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); - if (response.StatusCode == HttpStatusCode.OK) - { - Bitmap image = new Bitmap(response.GetResponseStream()); - Size newsize; - - // TODO: make this a bit less hard coded - if ((image.Height < 64) && (image.Width < 64)) - { - newsize = new Size(32, 32); - } - else if ((image.Height < 128) && (image.Width < 128)) - { - newsize = new Size(64, 64); - } - else if ((image.Height < 256) && (image.Width < 256)) - { - newsize = new Size(128, 128); - } - else if ((image.Height < 512 && image.Width < 512)) - { - newsize = new Size(256, 256); - } - else if ((image.Height < 1024 && image.Width < 1024)) - { - newsize = new Size(512, 512); - } - else - { - newsize = new Size(1024, 1024); - } - - Bitmap resize = new Bitmap(image, newsize); - byte[] imageJ2000 = new byte[0]; - - try - { - imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); - } - catch (Exception) - { - Console.WriteLine( - "[LOADIMAGEURLMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); - } - - m_textureManager.ReturnData(state.RequestID, imageJ2000); - } - } - catch (WebException) - { - - } - } - - #region Nested type: RequestState - - public class RequestState - { - public HttpWebRequest Request = null; - public UUID RequestID = UUID.Zero; - public int TimeOfRequest = 0; - - public RequestState(HttpWebRequest request, UUID requestID) - { - Request = request; - RequestID = requestID; - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs deleted file mode 100644 index 60806a7..0000000 --- a/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.Globalization; -using System.IO; -using System.Net; -using OpenMetaverse; -using OpenMetaverse.Imaging; -using Nini.Config; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -//using Cairo; - -namespace OpenSim.Region.Environment.Modules.Scripting.VectorRender -{ - public class VectorRenderModule : IRegionModule, IDynamicTextureRender - { - private string m_name = "VectorRenderModule"; - private Scene m_scene; - private IDynamicTextureManager m_textureManager; - - public VectorRenderModule() - { - } - - #region IDynamicTextureRender Members - - public string GetContentType() - { - return ("vector"); - } - - public string GetName() - { - return m_name; - } - - public bool SupportsAsynchronous() - { - return true; - } - - public byte[] ConvertUrl(string url, string extraParams) - { - return null; - } - - public byte[] ConvertStream(Stream data, string extraParams) - { - return null; - } - - public bool AsyncConvertUrl(UUID id, string url, string extraParams) - { - return false; - } - - public bool AsyncConvertData(UUID id, string bodyData, string extraParams) - { - Draw(bodyData, id, extraParams); - return true; - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (m_scene == null) - { - m_scene = scene; - } - } - - public void PostInitialise() - { - m_textureManager = m_scene.RequestModuleInterface(); - if (m_textureManager != null) - { - m_textureManager.RegisterRender(GetContentType(), this); - } - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void Draw(string data, UUID id, string extraParams) - { - // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha - // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 - int width = 256; - int height = 256; - int alpha = 255; // 0 is transparent - - char[] paramDelimiter = { ',' }; - char[] nvpDelimiter = { ':' }; - - extraParams = extraParams.Trim(); - extraParams = extraParams.ToLower(); - - string[] nvps = extraParams.Split(paramDelimiter); - - int temp = -1; - foreach (string pair in nvps) - { - string[] nvp = pair.Split(nvpDelimiter); - string name = ""; - string value = ""; - - if (nvp[0] != null) - { - name = nvp[0].Trim(); - } - - if (nvp.Length == 2) - { - value = nvp[1].Trim(); - } - - switch (name) - { - case "width": - temp = parseIntParam(value); - if (temp != -1) - { - if (temp < 1) - { - width = 1; - } - else if (temp > 2048) - { - width = 2048; - } - else - { - width = temp; - } - } - break; - case "height": - temp = parseIntParam(value); - if (temp != -1) - { - if (temp < 1) - { - height = 1; - } - else if (temp > 2048) - { - height = 2048; - } - else - { - height = temp; - } - } - break; - case "alpha": - temp = parseIntParam(value); - if (temp != -1) - { - if (temp < 0) - { - alpha = 0; - } - else if (temp > 255) - { - alpha = 255; - } - else - { - alpha = temp; - } - } - break; - case "": - // blank string has been passed do nothing just use defaults - break; - default: // this is all for backwards compat, all a bit ugly hopfully can be removed in future - // could be either set alpha or just an int - if (name == "setalpha") - { - alpha = 0; // set the texture to have transparent background (maintains backwards compat) - } - else - { - // this function used to accept an int on its own that represented both - // width and height, this is to maintain backwards compat, could be removed - // but would break existing scripts - temp = parseIntParam(name); - if (temp != -1) - { - if (temp > 1024) - temp = 1024; - - if (temp < 128) - temp = 128; - - width = temp; - height = temp; - } - } - break; - } - - } - - Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - - Graphics graph = Graphics.FromImage(bitmap); - - // this is really just to save people filling the - // background white in their scripts, only do when fully opaque - if (alpha == 255) - { - graph.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height); - } - - for (int w = 0; w < bitmap.Width; w++) - { - for (int h = 0; h < bitmap.Height; h++) - { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); - } - } - - - GDIDraw(data, graph); - - byte[] imageJ2000 = new byte[0]; - - try - { - imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); - } - catch (Exception) - { - Console.WriteLine( - "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); - } - m_textureManager.ReturnData(id, imageJ2000); - } - - private int parseIntParam(string strInt) - { - int parsed; - try - { - parsed = Convert.ToInt32(strInt); - } - catch (Exception) - { - //Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used - // Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString()); - parsed = -1; - } - - return parsed; - - } - - -/* - private void CairoDraw(string data, System.Drawing.Graphics graph) - { - using (Win32Surface draw = new Win32Surface(graph.GetHdc())) - { - Context contex = new Context(draw); - - contex.Antialias = Antialias.None; //fastest method but low quality - contex.LineWidth = 7; - char[] lineDelimiter = { ';' }; - char[] partsDelimiter = { ',' }; - string[] lines = data.Split(lineDelimiter); - - foreach (string line in lines) - { - string nextLine = line.Trim(); - - if (nextLine.StartsWith("MoveTO")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, ref x, ref y); - contex.MoveTo(x, y); - } - else if (nextLine.StartsWith("LineTo")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, ref x, ref y); - contex.LineTo(x, y); - contex.Stroke(); - } - } - } - graph.ReleaseHdc(); - } -*/ - - private void GDIDraw(string data, Graphics graph) - { - Point startPoint = new Point(0, 0); - Point endPoint = new Point(0, 0); - Pen drawPen = new Pen(Color.Black, 7); - string fontName = "Arial"; - float fontSize = 14; - Font myFont = new Font(fontName, fontSize); - SolidBrush myBrush = new SolidBrush(Color.Black); - char[] lineDelimiter = {';'}; - char[] partsDelimiter = {','}; - string[] lines = data.Split(lineDelimiter); - - foreach (string line in lines) - { - string nextLine = line.Trim(); - //replace with switch, or even better, do some proper parsing - if (nextLine.StartsWith("MoveTo")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); - startPoint.X = (int) x; - startPoint.Y = (int) y; - } - else if (nextLine.StartsWith("LineTo")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawLine(drawPen, startPoint, endPoint); - startPoint.X = endPoint.X; - startPoint.Y = endPoint.Y; - } - else if (nextLine.StartsWith("Text")) - { - nextLine = nextLine.Remove(0, 4); - nextLine = nextLine.Trim(); - graph.DrawString(nextLine, myFont, myBrush, startPoint); - } - else if (nextLine.StartsWith("Image")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - Image image = ImageHttpRequest(nextLine); - graph.DrawImage(image, (float) startPoint.X, (float) startPoint.Y, x, y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("Rectangle")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("FillRectangle")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("Ellipse")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("FontSize")) - { - nextLine = nextLine.Remove(0, 8); - nextLine = nextLine.Trim(); - fontSize = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - myFont = new Font(fontName, fontSize); - } - else if (nextLine.StartsWith("FontName")) - { - nextLine = nextLine.Remove(0, 8); - fontName = nextLine.Trim(); - myFont = new Font(fontName, fontSize); - } - else if (nextLine.StartsWith("PenSize")) - { - nextLine = nextLine.Remove(0, 7); - nextLine = nextLine.Trim(); - float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - drawPen.Width = size; - } - else if (nextLine.StartsWith("PenColour")) - { - nextLine = nextLine.Remove(0, 9); - nextLine = nextLine.Trim(); - int hex = 0; - - Color newColour; - if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) - { - newColour = Color.FromArgb(hex); - } - else - { - // this doesn't fail, it just returns black if nothing is found - newColour = Color.FromName(nextLine); - } - - myBrush.Color = newColour; - drawPen.Color = newColour; - } - } - } - - private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) - { - line = line.Remove(0, startLength); - string[] parts = line.Split(partsDelimiter); - if (parts.Length == 2) - { - string xVal = parts[0].Trim(); - string yVal = parts[1].Trim(); - x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); - y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); - } - else if (parts.Length > 2) - { - string xVal = parts[0].Trim(); - string yVal = parts[1].Trim(); - x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); - y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); - - line = ""; - for (int i = 2; i < parts.Length; i++) - { - line = line + parts[i].Trim(); - line = line + " "; - } - } - } - - private Bitmap ImageHttpRequest(string url) - { - WebRequest request = HttpWebRequest.Create(url); -//Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. -//Ckrinke Stream str = null; - HttpWebResponse response = (HttpWebResponse) (request).GetResponse(); - if (response.StatusCode == HttpStatusCode.OK) - { - Bitmap image = new Bitmap(response.GetResponseStream()); - return image; - } - - return null; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs deleted file mode 100644 index 258734d..0000000 --- a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs +++ /dev/null @@ -1,726 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using OpenMetaverse; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -// using log4net; -// using System.Reflection; - - -/***************************************************** - * - * WorldCommModule - * - * - * Holding place for world comms - basically llListen - * function implementation. - * - * lLListen(integer channel, string name, key id, string msg) - * The name, id, and msg arguments specify the filtering - * criteria. You can pass the empty string - * (or NULL_KEY for id) for these to set a completely - * open filter; this causes the listen() event handler to be - * invoked for all chat on the channel. To listen only - * for chat spoken by a specific object or avatar, - * specify the name and/or id arguments. To listen - * only for a specific command, specify the - * (case-sensitive) msg argument. If msg is not empty, - * listener will only hear strings which are exactly equal - * to msg. You can also use all the arguments to establish - * the most restrictive filtering criteria. - * - * It might be useful for each listener to maintain a message - * digest, with a list of recent messages by UUID. This can - * be used to prevent in-world repeater loops. However, the - * linden functions do not have this capability, so for now - * thats the way it works. - * Instead it blocks messages originating from the same prim. - * (not Object!) - * - * For LSL compliance, note the following: - * (Tested again 1.21.1 on May 2, 2008) - * 1. 'id' has to be parsed into a UUID. None-UUID keys are - * to be replaced by the ZeroID key. (Well, TryParse does - * that for us. - * 2. Setting up an listen event from the same script, with the - * same filter settings (including step 1), returns the same - * handle as the original filter. - * 3. (TODO) handles should be script-local. Starting from 1. - * Might be actually easier to map the global handle into - * script-local handle in the ScriptEngine. Not sure if its - * worth the effort tho. - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm -{ - public class WorldCommModule : IRegionModule, IWorldComm - { - // private static readonly ILog m_log = - // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private ListenerManager m_listenerManager; - private Queue m_pending; - private Queue m_pendingQ; - private Scene m_scene; - private int m_whisperdistance = 10; - private int m_saydistance = 30; - private int m_shoutdistance = 100; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - // wrap this in a try block so that defaults will work if - // the config file doesn't specify otherwise. - int maxlisteners = 1000; - int maxhandles = 64; - try - { - m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); - m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); - m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); - maxlisteners = config.Configs["Chat"].GetInt("max_listens_per_region", maxlisteners); - maxhandles = config.Configs["Chat"].GetInt("max_listens_per_script", maxhandles); - } - catch (Exception) - { - } - if (maxlisteners < 1) maxlisteners = int.MaxValue; - if (maxhandles < 1) maxhandles = int.MaxValue; - - m_scene = scene; - m_scene.RegisterModuleInterface(this); - m_listenerManager = new ListenerManager(maxlisteners, maxhandles); - m_scene.EventManager.OnChatFromClient += DeliverClientMessage; - m_scene.EventManager.OnChatBroadcast += DeliverClientMessage; - m_pendingQ = new Queue(); - m_pending = Queue.Synchronized(m_pendingQ); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "WorldCommModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region IWorldComm Members - - /// - /// Create a listen event callback with the specified filters. - /// The parameters localID,itemID are needed to uniquely identify - /// the script during 'peek' time. Parameter hostID is needed to - /// determine the position of the script. - /// - /// localID of the script engine - /// UUID of the script engine - /// UUID of the SceneObjectPart - /// channel to listen on - /// name to filter on - /// key to filter on (user given, could be totally faked) - /// msg to filter on - /// number of the scripts handle - public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) - { - return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); - } - - /// - /// Sets the listen event with handle as active (active = TRUE) or inactive (active = FALSE). - /// The handle used is returned from Listen() - /// - /// UUID of the script engine - /// handle returned by Listen() - /// temp. activate or deactivate the Listen() - public void ListenControl(UUID itemID, int handle, int active) - { - if (active == 1) - m_listenerManager.Activate(itemID, handle); - else if (active == 0) - m_listenerManager.Dectivate(itemID, handle); - } - - /// - /// Removes the listen event callback with handle - /// - /// UUID of the script engine - /// handle returned by Listen() - public void ListenRemove(UUID itemID, int handle) - { - m_listenerManager.Remove(itemID, handle); - } - - /// - /// Removes all listen event callbacks for the given itemID - /// (script engine) - /// - /// UUID of the script engine - public void DeleteListener(UUID itemID) - { - m_listenerManager.DeleteListener(itemID); - } - - - protected static Vector3 CenterOfRegion = new Vector3(128, 128, 20); - - public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg) - { - Vector3 position; - SceneObjectPart source; - ScenePresence avatar; - - if ((source = m_scene.GetSceneObjectPart(id)) != null) - position = source.AbsolutePosition; - else if ((avatar = m_scene.GetScenePresence(id)) != null) - position = avatar.AbsolutePosition; - else if (ChatTypeEnum.Region == type) - position = CenterOfRegion; - else - return; - - DeliverMessage(type, channel, name, id, msg, position); - } - - /// - /// This method scans over the objects which registered an interest in listen callbacks. - /// For everyone it finds, it checks if it fits the given filter. If it does, then - /// enqueue the message for delivery to the objects listen event handler. - /// The enqueued ListenerInfo no longer has filter values, but the actually trigged values. - /// Objects that do an llSay have their messages delivered here and for nearby avatars, - /// the OnChatFromClient event is used. - /// - /// type of delvery (whisper,say,shout or regionwide) - /// channel to sent on - /// name of sender (object or avatar) - /// key of sender (object or avatar) - /// msg to sent - public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position) - { - // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}", - // type, channel, name, id, msg); - - // Determine which listen event filters match the given set of arguments, this results - // in a limited set of listeners, each belonging a host. If the host is in range, add them - // to the pending queue. - foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) - { - // Dont process if this message is from yourself! - if (li.GetHostID().Equals(id)) - continue; - - SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); - if (sPart == null) - continue; - - double dis = Util.GetDistanceTo(sPart.AbsolutePosition, position); - switch (type) - { - case ChatTypeEnum.Whisper: - if (dis < m_whisperdistance) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); - } - } - break; - - case ChatTypeEnum.Say: - if (dis < m_saydistance) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); - } - } - break; - - case ChatTypeEnum.Shout: - if (dis < m_shoutdistance) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); - } - } - break; - - case ChatTypeEnum.Region: - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(new ListenerInfo(li,name,id,msg)); - } - break; - } - } - } - - /// - /// Are there any listen events ready to be dispatched? - /// - /// boolean indication - public bool HasMessages() - { - return (m_pending.Count > 0); - } - - /// - /// Pop the first availlable listen event from the queue - /// - /// ListenerInfo with filter filled in - public IWorldCommListenerInfo GetNextMessage() - { - ListenerInfo li = null; - - lock (m_pending.SyncRoot) - { - li = (ListenerInfo) m_pending.Dequeue(); - } - - return li; - } - - #endregion - - /******************************************************************** - * - * Listener Stuff - * - * *****************************************************************/ - - private void DeliverClientMessage(Object sender, OSChatMessage e) - { - if (null != e.Sender) - DeliverMessage(e.Type, e.Channel, e.Sender.Name, e.Sender.AgentId, e.Message, e.Position); - else - DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero, e.Message, e.Position); - } - - public Object[] GetSerializationData(UUID itemID) - { - return m_listenerManager.GetSerializationData(itemID); - } - - public void CreateFromData(uint localID, UUID itemID, UUID hostID, - Object[] data) - { - m_listenerManager.AddFromData(localID, itemID, hostID, data); - } - } - - public class ListenerManager - { - private Dictionary> m_listeners = new Dictionary>(); - private int m_maxlisteners; - private int m_maxhandles; - private int m_curlisteners; - - public ListenerManager(int maxlisteners, int maxhandles) - { - m_maxlisteners = maxlisteners; - m_maxhandles = maxhandles; - m_curlisteners = 0; - } - - public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) - { - // do we already have a match on this particular filter event? - List coll = GetListeners(itemID, channel, name, id, msg); - - if (coll.Count > 0) - { - // special case, called with same filter settings, return same handle - // (2008-05-02, tested on 1.21.1 server, still holds) - return coll[0].GetHandle(); - } - - if (m_curlisteners < m_maxlisteners) - { - int newHandle = GetNewHandle(itemID); - - if (newHandle > 0) - { - ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); - - lock (m_listeners) - { - List listeners; - if (!m_listeners.TryGetValue(channel,out listeners)) - { - listeners = new List(); - m_listeners.Add(channel, listeners); - } - listeners.Add(li); - m_curlisteners++; - } - - return newHandle; - } - } - return -1; - } - - public void Remove(UUID itemID, int handle) - { - lock (m_listeners) - { - foreach (KeyValuePair> lis in m_listeners) - { - foreach (ListenerInfo li in lis.Value) - { - if (li.GetItemID().Equals(itemID) && li.GetHandle().Equals(handle)) - { - lis.Value.Remove(li); - if (lis.Value.Count == 0) - { - m_listeners.Remove(lis.Key); - m_curlisteners--; - } - // there should be only one, so we bail out early - return; - } - } - } - } - } - - public void DeleteListener(UUID itemID) - { - List emptyChannels = new List(); - List removedListeners = new List(); - - lock (m_listeners) - { - foreach (KeyValuePair> lis in m_listeners) - { - foreach (ListenerInfo li in lis.Value) - { - if (li.GetItemID().Equals(itemID)) - { - // store them first, else the enumerated bails on us - removedListeners.Add(li); - } - } - foreach (ListenerInfo li in removedListeners) - { - lis.Value.Remove(li); - m_curlisteners--; - } - removedListeners.Clear(); - if (lis.Value.Count == 0) - { - // again, store first, remove later - emptyChannels.Add(lis.Key); - } - } - foreach (int channel in emptyChannels) - { - m_listeners.Remove(channel); - } - } - } - - public void Activate(UUID itemID, int handle) - { - lock (m_listeners) - { - foreach (KeyValuePair> lis in m_listeners) - { - foreach (ListenerInfo li in lis.Value) - { - if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) - { - li.Activate(); - // only one, bail out - return; - } - } - } - } - } - - public void Dectivate(UUID itemID, int handle) - { - lock (m_listeners) - { - foreach (KeyValuePair> lis in m_listeners) - { - foreach (ListenerInfo li in lis.Value) - { - if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) - { - li.Deactivate(); - // only one, bail out - return; - } - } - } - } - } - - // non-locked access, since its always called in the context of the lock - private int GetNewHandle(UUID itemID) - { - List handles = new List(); - - // build a list of used keys for this specific itemID... - foreach (KeyValuePair> lis in m_listeners) - { - foreach (ListenerInfo li in lis.Value) - { - if (li.GetItemID().Equals(itemID)) - handles.Add(li.GetHandle()); - } - } - - // Note: 0 is NOT a valid handle for llListen() to return - for (int i = 1; i <= m_maxhandles; i++) - { - if (!handles.Contains(i)) - return i; - } - - return -1; - } - - // Theres probably a more clever and efficient way to - // do this, maybe with regex. - // PM2008: Ha, one could even be smart and define a specialized Enumerator. - public List GetListeners(UUID itemID, int channel, string name, UUID id, string msg) - { - List collection = new List(); - - lock (m_listeners) - { - List listeners; - if (!m_listeners.TryGetValue(channel,out listeners)) - { - return collection; - } - - foreach (ListenerInfo li in listeners) - { - if (!li.IsActive()) - { - continue; - } - if (!itemID.Equals(UUID.Zero) && !li.GetItemID().Equals(itemID)) - { - continue; - } - if (li.GetName().Length > 0 && !li.GetName().Equals(name)) - { - continue; - } - if (!li.GetID().Equals(UUID.Zero) && !li.GetID().Equals(id)) - { - continue; - } - if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) - { - continue; - } - collection.Add(li); - } - } - return collection; - } - - public Object[] GetSerializationData(UUID itemID) - { - List data = new List(); - - foreach (List list in m_listeners.Values) - { - foreach (ListenerInfo l in list) - { - if (l.GetItemID() == itemID) - data.AddRange(l.GetSerializationData()); - } - } - return (Object[])data.ToArray(); - } - - public void AddFromData(uint localID, UUID itemID, UUID hostID, - Object[] data) - { - int idx = 0; - Object[] item = new Object[6]; - - while (idx < data.Length) - { - Array.Copy(data, idx, item, 0, 6); - - ListenerInfo info = - ListenerInfo.FromData(localID, itemID, hostID, item); - - if (!m_listeners.ContainsKey((int)item[2])) - m_listeners.Add((int)item[2], new List()); - m_listeners[(int)item[2]].Add(info); - - idx+=6; - } - } - } - - public class ListenerInfo: IWorldCommListenerInfo - { - private bool m_active; // Listener is active or not - private int m_handle; // Assigned handle of this listener - private uint m_localID; // Local ID from script engine - private UUID m_itemID; // ID of the host script engine - private UUID m_hostID; // ID of the host/scene part - private int m_channel; // Channel - private UUID m_id; // ID to filter messages from - private string m_name; // Object name to filter messages from - private string m_message; // The message - - public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) - { - Initialise(handle, localID, ItemID, hostID, channel, name, id, message); - } - - public ListenerInfo(ListenerInfo li, string name, UUID id, string message) - { - Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); - } - - private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, - UUID id, string message) - { - m_active = true; - m_handle = handle; - m_localID = localID; - m_itemID = ItemID; - m_hostID = hostID; - m_channel = channel; - m_name = name; - m_id = id; - m_message = message; - } - - public Object[] GetSerializationData() - { - Object[] data = new Object[6]; - - data[0] = m_active; - data[1] = m_handle; - data[2] = m_channel; - data[3] = m_name; - data[4] = m_id; - data[5] = m_message; - - return data; - } - - public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) - { - ListenerInfo linfo = new ListenerInfo((int)data[1], localID, - ItemID, hostID, (int)data[2], (string)data[3], - (UUID)data[4], (string)data[5]); - linfo.m_active=(bool)data[0]; - - return linfo; - } - - public UUID GetItemID() - { - return m_itemID; - } - - public UUID GetHostID() - { - return m_hostID; - } - - public int GetChannel() - { - return m_channel; - } - - public uint GetLocalID() - { - return m_localID; - } - - public int GetHandle() - { - return m_handle; - } - - public string GetMessage() - { - return m_message; - } - - public string GetName() - { - return m_name; - } - - public bool IsActive() - { - return m_active; - } - - public void Deactivate() - { - m_active = false; - } - - public void Activate() - { - m_active = true; - } - - public UUID GetID() - { - return m_id; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs deleted file mode 100644 index fb86731..0000000 --- a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs +++ /dev/null @@ -1,726 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Reflection; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -/***************************************************** - * - * XMLRPCModule - * - * Module for accepting incoming communications from - * external XMLRPC client and calling a remote data - * procedure for a registered data channel/prim. - * - * - * 1. On module load, open a listener port - * 2. Attach an XMLRPC handler - * 3. When a request is received: - * 3.1 Parse into components: channel key, int, string - * 3.2 Look up registered channel listeners - * 3.3 Call the channel (prim) remote data method - * 3.4 Capture the response (llRemoteDataReply) - * 3.5 Return response to client caller - * 3.6 If no response from llRemoteDataReply within - * RemoteReplyScriptTimeout, generate script timeout fault - * - * Prims in script must: - * 1. Open a remote data channel - * 1.1 Generate a channel ID - * 1.2 Register primid,channelid pair with module - * 2. Implement the remote data procedure handler - * - * llOpenRemoteDataChannel - * llRemoteDataReply - * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval) - * llCloseRemoteDataChannel - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.XMLRPC -{ - public class XMLRPCModule : IRegionModule, IXMLRPC - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private string m_name = "XMLRPCModule"; - - // - private Dictionary m_openChannels; - private Dictionary m_pendingSRDResponses; - private int m_remoteDataPort = 0; - - private Dictionary m_rpcPending; - private Dictionary m_rpcPendingResponses; - private List m_scenes = new List(); - private int RemoteReplyScriptTimeout = 9000; - private int RemoteReplyScriptWait = 300; - private object XMLRPCListLock = new object(); - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - // We need to create these early because the scripts might be calling - // But since this gets called for every region, we need to make sure they - // get called only one time (or we lose any open channels) - if (null == m_openChannels) - { - m_openChannels = new Dictionary(); - m_rpcPending = new Dictionary(); - m_rpcPendingResponses = new Dictionary(); - m_pendingSRDResponses = new Dictionary(); - - try - { - m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort); - } - catch (Exception) - { - } - } - - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - - scene.RegisterModuleInterface(this); - } - } - - public void PostInitialise() - { - if (IsEnabled()) - { - // Start http server - // Attach xmlrpc handlers - m_log.Info("[REMOTE_DATA]: " + - "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); - BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); - httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); - httpServer.Start(); - } - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region IXMLRPC Members - - public bool IsEnabled() - { - return (m_remoteDataPort > 0); - } - - /********************************************** - * OpenXMLRPCChannel - * - * Generate a UUID channel key and add it and - * the prim id to dictionary - * - * A custom channel key can be proposed. - * Otherwise, passing UUID.Zero will generate - * and return a random channel - * - * First check if there is a channel assigned for - * this itemID. If there is, then someone called - * llOpenRemoteDataChannel twice. Just return the - * original channel. Other option is to delete the - * current channel and assign a new one. - * - * ********************************************/ - - public UUID OpenXMLRPCChannel(uint localID, UUID itemID, UUID channelID) - { - UUID newChannel = UUID.Zero; - - // This should no longer happen, but the check is reasonable anyway - if (null == m_openChannels) - { - m_log.Warn("[RemoteDataReply] Attempt to open channel before initialization is complete"); - return newChannel; - } - - //Is a dupe? - foreach (RPCChannelInfo ci in m_openChannels.Values) - { - if (ci.GetItemID().Equals(itemID)) - { - // return the original channel ID for this item - newChannel = ci.GetChannelID(); - break; - } - } - - if (newChannel == UUID.Zero) - { - newChannel = (channelID == UUID.Zero) ? UUID.Random() : channelID; - RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, newChannel); - lock (XMLRPCListLock) - { - m_openChannels.Add(newChannel, rpcChanInfo); - } - } - - return newChannel; - } - - // Delete channels based on itemID - // for when a script is deleted - public void DeleteChannels(UUID itemID) - { - if (m_openChannels != null) - { - ArrayList tmp = new ArrayList(); - - lock (XMLRPCListLock) - { - foreach (RPCChannelInfo li in m_openChannels.Values) - { - if (li.GetItemID().Equals(itemID)) - { - tmp.Add(itemID); - } - } - - IEnumerator tmpEnumerator = tmp.GetEnumerator(); - while (tmpEnumerator.MoveNext()) - m_openChannels.Remove((UUID) tmpEnumerator.Current); - } - } - } - - /********************************************** - * Remote Data Reply - * - * Response to RPC message - * - *********************************************/ - - public void RemoteDataReply(string channel, string message_id, string sdata, int idata) - { - UUID message_key = new UUID(message_id); - UUID channel_key = new UUID(channel); - - RPCRequestInfo rpcInfo = null; - - if (message_key == UUID.Zero) - { - foreach (RPCRequestInfo oneRpcInfo in m_rpcPendingResponses.Values) - if (oneRpcInfo.GetChannelKey() == channel_key) - rpcInfo = oneRpcInfo; - } - else - { - m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo); - } - - if (rpcInfo != null) - { - rpcInfo.SetStrRetval(sdata); - rpcInfo.SetIntRetval(idata); - rpcInfo.SetProcessed(true); - m_rpcPendingResponses.Remove(message_key); - } - else - { - m_log.Warn("[RemoteDataReply]: Channel or message_id not found"); - } - } - - /********************************************** - * CloseXMLRPCChannel - * - * Remove channel from dictionary - * - *********************************************/ - - public void CloseXMLRPCChannel(UUID channelKey) - { - if (m_openChannels.ContainsKey(channelKey)) - m_openChannels.Remove(channelKey); - } - - - public bool hasRequests() - { - lock (XMLRPCListLock) - { - if (m_rpcPending != null) - return (m_rpcPending.Count > 0); - else - return false; - } - } - - public IXmlRpcRequestInfo GetNextCompletedRequest() - { - if (m_rpcPending != null) - { - lock (XMLRPCListLock) - { - foreach (UUID luid in m_rpcPending.Keys) - { - RPCRequestInfo tmpReq; - - if (m_rpcPending.TryGetValue(luid, out tmpReq)) - { - if (!tmpReq.IsProcessed()) return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedRequest(UUID id) - { - lock (XMLRPCListLock) - { - RPCRequestInfo tmp; - if (m_rpcPending.TryGetValue(id, out tmp)) - { - m_rpcPending.Remove(id); - m_rpcPendingResponses.Add(id, tmp); - } - else - { - Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST"); - } - } - } - - public UUID SendRemoteData(uint localID, UUID itemID, string channel, string dest, int idata, string sdata) - { - SendRemoteDataRequest req = new SendRemoteDataRequest( - localID, itemID, channel, dest, idata, sdata - ); - m_pendingSRDResponses.Add(req.GetReqID(), req); - req.Process(); - return req.ReqID; - } - - public IServiceRequest GetNextCompletedSRDRequest() - { - if (m_pendingSRDResponses != null) - { - lock (XMLRPCListLock) - { - foreach (UUID luid in m_pendingSRDResponses.Keys) - { - SendRemoteDataRequest tmpReq; - - if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq)) - { - if (tmpReq.Finished) - return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedSRDRequest(UUID id) - { - lock (XMLRPCListLock) - { - SendRemoteDataRequest tmpReq; - if (m_pendingSRDResponses.TryGetValue(id, out tmpReq)) - { - m_pendingSRDResponses.Remove(id); - } - } - } - - public void CancelSRDRequests(UUID itemID) - { - if (m_pendingSRDResponses != null) - { - lock (XMLRPCListLock) - { - foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values) - { - if (li.ItemID.Equals(itemID)) - m_pendingSRDResponses.Remove(li.GetReqID()); - } - } - } - } - - #endregion - - public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request) - { - XmlRpcResponse response = new XmlRpcResponse(); - - Hashtable requestData = (Hashtable) request.Params[0]; - bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && - requestData.Contains("StringValue")); - - if (GoodXML) - { - UUID channel = new UUID((string) requestData["Channel"]); - RPCChannelInfo rpcChanInfo; - if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) - { - string intVal = Convert.ToInt32(requestData["IntValue"]).ToString(); - string strVal = (string) requestData["StringValue"]; - - RPCRequestInfo rpcInfo; - - lock (XMLRPCListLock) - { - rpcInfo = - new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, - intVal); - m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo); - } - - int timeoutCtr = 0; - - while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout)) - { - Thread.Sleep(RemoteReplyScriptWait); - timeoutCtr += RemoteReplyScriptWait; - } - if (rpcInfo.IsProcessed()) - { - Hashtable param = new Hashtable(); - param["StringValue"] = rpcInfo.GetStrRetval(); - param["IntValue"] = rpcInfo.GetIntRetval(); - - ArrayList parameters = new ArrayList(); - parameters.Add(param); - - response.Value = parameters; - rpcInfo = null; - } - else - { - response.SetFault(-1, "Script timeout"); - rpcInfo = null; - } - } - else - { - response.SetFault(-1, "Invalid channel"); - } - } - - return response; - } - } - - public class RPCRequestInfo: IXmlRpcRequestInfo - { - private UUID m_ChannelKey; - private string m_IntVal; - private UUID m_ItemID; - private uint m_localID; - private UUID m_MessageID; - private bool m_processed; - private int m_respInt; - private string m_respStr; - private string m_StrVal; - - public RPCRequestInfo(uint localID, UUID itemID, UUID channelKey, string strVal, string intVal) - { - m_localID = localID; - m_StrVal = strVal; - m_IntVal = intVal; - m_ItemID = itemID; - m_ChannelKey = channelKey; - m_MessageID = UUID.Random(); - m_processed = false; - m_respStr = String.Empty; - m_respInt = 0; - } - - public bool IsProcessed() - { - return m_processed; - } - - public UUID GetChannelKey() - { - return m_ChannelKey; - } - - public void SetProcessed(bool processed) - { - m_processed = processed; - } - - public void SetStrRetval(string resp) - { - m_respStr = resp; - } - - public string GetStrRetval() - { - return m_respStr; - } - - public void SetIntRetval(int resp) - { - m_respInt = resp; - } - - public int GetIntRetval() - { - return m_respInt; - } - - public uint GetLocalID() - { - return m_localID; - } - - public UUID GetItemID() - { - return m_ItemID; - } - - public string GetStrVal() - { - return m_StrVal; - } - - public int GetIntValue() - { - return int.Parse(m_IntVal); - } - - public UUID GetMessageID() - { - return m_MessageID; - } - } - - public class RPCChannelInfo - { - private UUID m_ChannelKey; - private UUID m_itemID; - private uint m_localID; - - public RPCChannelInfo(uint localID, UUID itemID, UUID channelID) - { - m_ChannelKey = channelID; - m_localID = localID; - m_itemID = itemID; - } - - public UUID GetItemID() - { - return m_itemID; - } - - public UUID GetChannelID() - { - return m_ChannelKey; - } - - public uint GetLocalID() - { - return m_localID; - } - } - - public class SendRemoteDataRequest: IServiceRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public string Channel; - public string DestURL; - private bool _finished; - public bool Finished - { - get { return _finished; } - set { _finished = value; } - } - private Thread httpThread; - public int Idata; - private UUID _itemID; - public UUID ItemID - { - get { return _itemID; } - set { _itemID = value; } - } - private uint _localID; - public uint LocalID - { - get { return _localID; } - set { _localID = value; } - } - private UUID _reqID; - public UUID ReqID - { - get { return _reqID; } - set { _reqID = value; } - } - public XmlRpcRequest Request; - public int ResponseIdata; - public string ResponseSdata; - public string Sdata; - - public SendRemoteDataRequest(uint localID, UUID itemID, string channel, string dest, int idata, string sdata) - { - this.Channel = channel; - DestURL = dest; - this.Idata = idata; - this.Sdata = sdata; - ItemID = itemID; - LocalID = localID; - - ReqID = UUID.Random(); - } - - public void Process() - { - httpThread = new Thread(SendRequest); - httpThread.Name = "HttpRequestThread"; - httpThread.Priority = ThreadPriority.BelowNormal; - httpThread.IsBackground = true; - _finished = false; - httpThread.Start(); - ThreadTracker.Add(httpThread); - } - - /* - * TODO: More work on the response codes. Right now - * returning 200 for success or 499 for exception - */ - - public void SendRequest() - { - Hashtable param = new Hashtable(); - - // Check if channel is an UUID - // if not, use as method name - UUID parseUID; - string mName = "llRemoteData"; - if ((Channel != null) && (Channel != "")) - if (!UUID.TryParse(Channel, out parseUID)) - mName = Channel; - else - param["Channel"] = Channel; - - param["StringValue"] = Sdata; - param["IntValue"] = Convert.ToString(Idata); - - ArrayList parameters = new ArrayList(); - parameters.Add(param); - XmlRpcRequest req = new XmlRpcRequest(mName, parameters); - try - { - XmlRpcResponse resp = req.Send(DestURL, 30000); - if (resp != null) - { - Hashtable respParms; - if (resp.Value.GetType().Equals(typeof(System.Collections.Hashtable))) - { - respParms = (Hashtable) resp.Value; - } - else - { - ArrayList respData = (ArrayList) resp.Value; - respParms = (Hashtable) respData[0]; - } - if (respParms != null) - { - if (respParms.Contains("StringValue")) - { - Sdata = (string) respParms["StringValue"]; - } - if (respParms.Contains("IntValue")) - { - Idata = Convert.ToInt32((string) respParms["IntValue"]); - } - if (respParms.Contains("faultString")) - { - Sdata = (string) respParms["faultString"]; - } - if (respParms.Contains("faultCode")) - { - Idata = Convert.ToInt32(respParms["faultCode"]); - } - } - } - } - catch (Exception we) - { - Sdata = we.Message; - m_log.Warn("[SendRemoteDataRequest]: Request failed"); - m_log.Warn(we.StackTrace); - } - - _finished = true; - } - - public void Stop() - { - try - { - httpThread.Abort(); - } - catch (Exception) - { - } - } - - public UUID GetReqID() - { - return ReqID; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs deleted file mode 100644 index 4151c88..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveConstants.cs +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using OpenMetaverse; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Constants for the archiving module - /// - public class ArchiveConstants - { - /// - /// The location of the archive control file - /// - public static readonly string CONTROL_FILE_PATH = "archive.xml"; - - /// - /// Path for the assets held in an archive - /// - public static readonly string ASSETS_PATH = "assets/"; - - /// - /// Path for the assets metadata file - /// - //public static readonly string ASSETS_METADATA_PATH = "assets.xml"; - - /// - /// Path for the prims file - /// - public static readonly string OBJECTS_PATH = "objects/"; - - /// - /// Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. - /// - public static readonly string TERRAINS_PATH = "terrains/"; - - /// - /// Path for region settings. - /// - public static readonly string SETTINGS_PATH = "settings/"; - - /// - /// The character the separates the uuid from extension information in an archived asset filename - /// - public static readonly string ASSET_EXTENSION_SEPARATOR = "_"; - - /// - /// Extensions used for asset types in the archive - /// - public static readonly IDictionary ASSET_TYPE_TO_EXTENSION = new Dictionary(); - public static readonly IDictionary EXTENSION_TO_ASSET_TYPE = new Dictionary(); - - static ArchiveConstants() - { - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Animation] = ASSET_EXTENSION_SEPARATOR + "animation.bvh"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Bodypart] = ASSET_EXTENSION_SEPARATOR + "bodypart.txt"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.CallingCard] = ASSET_EXTENSION_SEPARATOR + "callingcard.txt"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Clothing] = ASSET_EXTENSION_SEPARATOR + "clothing.txt"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Folder] = ASSET_EXTENSION_SEPARATOR + "folder.txt"; // Not sure if we'll ever see this - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Gesture] = ASSET_EXTENSION_SEPARATOR + "gesture.txt"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageJPEG] = ASSET_EXTENSION_SEPARATOR + "image.jpg"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.ImageTGA] = ASSET_EXTENSION_SEPARATOR + "image.tga"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Landmark] = ASSET_EXTENSION_SEPARATOR + "landmark.txt"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LostAndFoundFolder] = ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"; // Not sure if we'll ever see this - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLBytecode] = ASSET_EXTENSION_SEPARATOR + "bytecode.lso"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLText] = ASSET_EXTENSION_SEPARATOR + "script.lsl"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Notecard] = ASSET_EXTENSION_SEPARATOR + "notecard.txt"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Object] = ASSET_EXTENSION_SEPARATOR + "object.xml"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.RootFolder] = ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"; // Not sure if we'll ever see this - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Simstate] = ASSET_EXTENSION_SEPARATOR + "simstate.bin"; // Not sure if we'll ever see this - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SnapshotFolder] = ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"; // Not sure if we'll ever see this - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Sound] = ASSET_EXTENSION_SEPARATOR + "sound.ogg"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV] = ASSET_EXTENSION_SEPARATOR + "sound.wav"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga"; - ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this - - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "callingcard.txt"] = (sbyte)AssetType.CallingCard; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "clothing.txt"] = (sbyte)AssetType.Clothing; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "folder.txt"] = (sbyte)AssetType.Folder; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "gesture.txt"] = (sbyte)AssetType.Gesture; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.jpg"] = (sbyte)AssetType.ImageJPEG; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "image.tga"] = (sbyte)AssetType.ImageTGA; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "landmark.txt"] = (sbyte)AssetType.Landmark; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"] = (sbyte)AssetType.LostAndFoundFolder; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bytecode.lso"] = (sbyte)AssetType.LSLBytecode; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "script.lsl"] = (sbyte)AssetType.LSLText; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "notecard.txt"] = (sbyte)AssetType.Notecard; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "object.xml"] = (sbyte)AssetType.Object; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"] = (sbyte)AssetType.RootFolder; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "simstate.bin"] = (sbyte)AssetType.Simstate; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "snapshotfolder.txt"] = (sbyte)AssetType.SnapshotFolder; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.ogg"] = (sbyte)AssetType.Sound; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "sound.wav"] = (sbyte)AssetType.SoundWAV; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA; - EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs deleted file mode 100644 index b507c52..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveReadRequest.cs +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Reflection; -using System.Xml; -using System.Net; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Terrain; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Handles an individual archive read request - /// - public class ArchiveReadRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); - - private Scene m_scene; - private Stream m_loadStream; - private string m_errorMessage; - - /// - /// Used to cache lookups for valid uuids. - /// - private IDictionary m_validUserUuids = new Dictionary(); - - public ArchiveReadRequest(Scene scene, string loadPath) - { - m_scene = scene; - m_loadStream = new GZipStream(GetStream(loadPath), CompressionMode.Decompress); - m_errorMessage = String.Empty; - } - - public ArchiveReadRequest(Scene scene, Stream loadStream) - { - m_scene = scene; - m_loadStream = loadStream; - } - - /// - /// Dearchive the region embodied in this request. - /// - public void DearchiveRegion() - { - // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions - DearchiveRegion0DotStar(); - } - - private void DearchiveRegion0DotStar() - { - int successfulAssetRestores = 0; - int failedAssetRestores = 0; - List serialisedSceneObjects = new List(); - - try - { - TarArchiveReader archive = new TarArchiveReader(m_loadStream); - - //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache); - - string filePath = "ERROR"; - - byte[] data; - TarArchiveReader.TarEntryType entryType; - - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) - { - //m_log.DebugFormat( - // "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length); - if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) - { - m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", - filePath); - } - else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - serialisedSceneObjects.Add(m_asciiEncoding.GetString(data)); - } -// else if (filePath.Equals(ArchiveConstants.ASSETS_METADATA_PATH)) -// { -// string xml = m_asciiEncoding.GetString(data); -// dearchiver.AddAssetMetadata(xml); -// } - else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - if (LoadAsset(filePath, data)) - successfulAssetRestores++; - else - failedAssetRestores++; - } - else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) - { - LoadTerrain(filePath, data); - } - else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) - { - LoadRegionSettings(filePath, data); - } - } - - //m_log.Debug("[ARCHIVER]: Reached end of archive"); - - archive.Close(); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[ARCHIVER]: Error loading oar file. Exception was: {0}", e); - m_errorMessage += e.ToString(); - m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage); - return; - } - - m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); - - if (failedAssetRestores > 0) - { - m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); - m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); - } - - m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); - m_scene.DeleteAllSceneObjects(); - - // Reload serialized prims - m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); - - IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface(); - ICollection sceneObjects = new List(); - - foreach (string serialisedSceneObject in serialisedSceneObjects) - { - SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); - - // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned - // on the same region server and multiple examples a single object archive to be imported - // to the same scene (when this is possible). - sceneObject.ResetIDs(); - - // Try to retain the original creator/owner/lastowner if their uuid is present on this grid - // otherwise, use the master avatar uuid instead - UUID masterAvatarId = m_scene.RegionInfo.MasterAvatarAssignedUUID; - - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - masterAvatarId = m_scene.RegionInfo.EstateSettings.EstateOwner; - - foreach (SceneObjectPart part in sceneObject.Children.Values) - { - if (!resolveUserUuid(part.CreatorID)) - part.CreatorID = masterAvatarId; - - if (!resolveUserUuid(part.OwnerID)) - part.OwnerID = masterAvatarId; - - if (!resolveUserUuid(part.LastOwnerID)) - part.LastOwnerID = masterAvatarId; - - // And zap any troublesome sit target information - part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); - part.SitTargetPosition = new Vector3(0, 0, 0); - - // Fix ownership/creator of inventory items - // Not doing so results in inventory items - // being no copy/no mod for everyone - TaskInventoryDictionary inv = part.TaskInventory; - foreach (KeyValuePair kvp in inv) - { - if (!resolveUserUuid(kvp.Value.OwnerID)) - { - kvp.Value.OwnerID = masterAvatarId; - } - if (!resolveUserUuid(kvp.Value.CreatorID)) - { - kvp.Value.CreatorID = masterAvatarId; - } - } - } - - if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) - { - sceneObjects.Add(sceneObject); - } - } - - m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjects.Count); - - int ignoredObjects = serialisedSceneObjects.Count - sceneObjects.Count; - - if (ignoredObjects > 0) - m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); - - m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); - - m_log.Debug("[ARCHIVER]: Starting scripts"); - - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - sceneObject.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 0); - } - - m_scene.EventManager.TriggerOarFileLoaded(m_errorMessage); - } - - /// - /// Look up the given user id to check whether it's one that is valid for this grid. - /// - /// - /// - private bool resolveUserUuid(UUID uuid) - { - if (!m_validUserUuids.ContainsKey(uuid)) - { - CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(uuid); - if (profile != null && profile.UserProfile != null) - m_validUserUuids.Add(uuid, true); - else - m_validUserUuids.Add(uuid, false); - } - - if (m_validUserUuids[uuid]) - return true; - else - return false; - } - - /// - /// Load an asset - /// - /// - /// - /// true if asset was successfully loaded, false otherwise - private bool LoadAsset(string assetPath, byte[] data) - { - // Right now we're nastily obtaining the UUID from the filename - string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); - int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR); - - if (i == -1) - { - m_log.ErrorFormat( - "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping", - assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR); - - return false; - } - - string extension = filename.Substring(i); - string uuid = filename.Remove(filename.Length - extension.Length); - - if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) - { - sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; - - //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); - - AssetBase asset = new AssetBase(new UUID(uuid), String.Empty); - asset.Metadata.Type = assetType; - asset.Data = data; - - m_scene.AssetCache.AddAsset(asset); - - /** - * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so - * it might be best done when dearchive takes place on a separate thread - if (asset.Type=AssetType.Texture) - { - IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface(); - if (cacheLayerDecode != null) - cacheLayerDecode.syncdecode(asset.FullID, asset.Data); - } - */ - - return true; - } - else - { - m_log.ErrorFormat( - "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}", - assetPath, extension); - - return false; - } - } - - /// - /// Load region settings data - /// - /// - /// - /// - /// true if settings were loaded successfully, false otherwise - /// - private bool LoadRegionSettings(string settingsPath, byte[] data) - { - RegionSettings loadedRegionSettings; - - try - { - loadedRegionSettings = RegionSettingsSerializer.Deserialize(data); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}", - settingsPath, e); - return false; - } - - RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; - - currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; - currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; - currentRegionSettings.AllowLandJoinDivide = loadedRegionSettings.AllowLandJoinDivide; - currentRegionSettings.AllowLandResell = loadedRegionSettings.AllowLandResell; - currentRegionSettings.BlockFly = loadedRegionSettings.BlockFly; - currentRegionSettings.BlockShowInSearch = loadedRegionSettings.BlockShowInSearch; - currentRegionSettings.BlockTerraform = loadedRegionSettings.BlockTerraform; - currentRegionSettings.DisableCollisions = loadedRegionSettings.DisableCollisions; - currentRegionSettings.DisablePhysics = loadedRegionSettings.DisablePhysics; - currentRegionSettings.DisableScripts = loadedRegionSettings.DisableScripts; - currentRegionSettings.Elevation1NE = loadedRegionSettings.Elevation1NE; - currentRegionSettings.Elevation1NW = loadedRegionSettings.Elevation1NW; - currentRegionSettings.Elevation1SE = loadedRegionSettings.Elevation1SE; - currentRegionSettings.Elevation1SW = loadedRegionSettings.Elevation1SW; - currentRegionSettings.Elevation2NE = loadedRegionSettings.Elevation2NE; - currentRegionSettings.Elevation2NW = loadedRegionSettings.Elevation2NW; - currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE; - currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW; - currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun; - currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus; - currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing; - currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit; - currentRegionSettings.TerrainRaiseLimit = loadedRegionSettings.TerrainRaiseLimit; - currentRegionSettings.TerrainTexture1 = loadedRegionSettings.TerrainTexture1; - currentRegionSettings.TerrainTexture2 = loadedRegionSettings.TerrainTexture2; - currentRegionSettings.TerrainTexture3 = loadedRegionSettings.TerrainTexture3; - currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4; - currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun; - currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; - - IEstateModule estateModule = m_scene.RequestModuleInterface(); - estateModule.sendRegionHandshakeToAll(); - - return true; - } - - /// - /// Load terrain data - /// - /// - /// - /// - /// true if terrain was resolved successfully, false otherwise. - /// - private bool LoadTerrain(string terrainPath, byte[] data) - { - ITerrainModule terrainModule = m_scene.RequestModuleInterface(); - - MemoryStream ms = new MemoryStream(data); - terrainModule.LoadFromStream(terrainPath, ms); - ms.Close(); - - m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath); - - return true; - } - - /// - /// Resolve path to a working FileStream - /// - private Stream GetStream(string path) - { - try - { - if (File.Exists(path)) - { - return new FileStream(path, FileMode.Open); - } - else - { - Uri uri = new Uri(path); // throw exception if not valid URI - if (uri.Scheme == "file") - { - return new FileStream(uri.AbsolutePath, FileMode.Open); - } - else - { - if (uri.Scheme != "http") - throw new Exception(String.Format("Unsupported URI scheme ({0})", path)); - - // OK, now we know we have an HTTP URI to work with - - return URIFetch(uri); - } - } - } - catch (Exception e) - { - throw new Exception(String.Format("Unable to create file input stream for {0}: {1}", path, e)); - } - } - - private static Stream URIFetch(Uri uri) - { - HttpWebRequest request = (HttpWebRequest) WebRequest.Create(uri); - - // request.Credentials = credentials; - - request.ContentLength = 0; - - WebResponse response = request.GetResponse(); - Stream file = response.GetResponseStream(); - - if (response.ContentType != "application/x-oar") - throw new Exception(String.Format("{0} does not identify an OAR file", uri.ToString())); - - if (response.ContentLength == 0) - throw new Exception(String.Format("{0} returned an empty file", uri.ToString())); - - // return new BufferedStream(file, (int) response.ContentLength); - return new BufferedStream(file, 1000000); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs deleted file mode 100644 index 9a06bf7..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestExecution.cs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Xml; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Serialiser; -using OpenSim.Region.Environment.Modules.World.Terrain; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Method called when all the necessary assets for an archive request have been received. - /// - public delegate void AssetsRequestCallback(IDictionary assetsFound, ICollection assetsNotFoundUuids); - - /// - /// Execute the write of an archive once we have received all the necessary data - /// - public class ArchiveWriteRequestExecution - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected ITerrainModule m_terrainModule; - protected IRegionSerialiserModule m_serialiser; - protected List m_sceneObjects; - protected Scene m_scene; - protected Stream m_saveStream; - - public ArchiveWriteRequestExecution( - List sceneObjects, - ITerrainModule terrainModule, - IRegionSerialiserModule serialiser, - Scene scene, - Stream saveStream) - { - m_sceneObjects = sceneObjects; - m_terrainModule = terrainModule; - m_serialiser = serialiser; - m_scene = scene; - m_saveStream = saveStream; - } - - protected internal void ReceivedAllAssets( - IDictionary assetsFound, ICollection assetsNotFoundUuids) - { - foreach (UUID uuid in assetsNotFoundUuids) - { - m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); - } - - m_log.InfoFormat( - "[ARCHIVER]: Received {0} of {1} assets requested", - assetsFound.Count, assetsFound.Count + assetsNotFoundUuids.Count); - - m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); - - TarArchiveWriter archive = new TarArchiveWriter(); - - // Write out control file - archive.AddFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile()); - - // Write out region settings - string settingsPath - = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); - archive.AddFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); - - // Write out terrain - string terrainPath - = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); - - MemoryStream ms = new MemoryStream(); - m_terrainModule.SaveToStream(terrainPath, ms); - archive.AddFile(terrainPath, ms.ToArray()); - ms.Close(); - - // Write out scene object metadata - foreach (SceneObjectGroup sceneObject in m_sceneObjects) - { - //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); - - Vector3 position = sceneObject.AbsolutePosition; - - string serializedObject = m_serialiser.SaveGroupToXml2(sceneObject); - string filename - = string.Format( - "{0}{1}_{2:000}-{3:000}-{4:000}__{5}.xml", - ArchiveConstants.OBJECTS_PATH, sceneObject.Name, - Math.Round(position.X), Math.Round(position.Y), Math.Round(position.Z), - sceneObject.UUID); - - archive.AddFile(filename, serializedObject); - } - - // Write out assets - AssetsArchiver assetsArchiver = new AssetsArchiver(assetsFound); - assetsArchiver.Archive(archive); - - archive.WriteTar(m_saveStream); - - m_log.InfoFormat("[ARCHIVER]: Wrote out OpenSimulator archive for {0}", m_scene.RegionInfo.RegionName); - - m_scene.EventManager.TriggerOarFileSaved(String.Empty); - } - - /// - /// Create the control file for a 0.2 version archive - /// - /// - public static string Create0p2ControlFile() - { - StringWriter sw = new StringWriter(); - XmlTextWriter xtw = new XmlTextWriter(sw); - xtw.Formatting = Formatting.Indented; - xtw.WriteStartDocument(); - xtw.WriteStartElement("archive"); - xtw.WriteAttributeString("major_version", "0"); - xtw.WriteAttributeString("minor_version", "2"); - xtw.WriteEndElement(); - - xtw.Flush(); - xtw.Close(); - - String s = sw.ToString(); - sw.Close(); - - return s; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs deleted file mode 100644 index 56604d6..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Serialiser; -using OpenSim.Region.Environment.Modules.World.Terrain; -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Prepare to write out an archive. - /// - public class ArchiveWriteRequestPreparation - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - protected Stream m_saveStream; - - /// - /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate - /// asset was found by the asset service. - /// - protected AssetBase m_requestedObjectAsset; - - /// - /// Signal whether we are currently waiting for the asset service to deliver an asset. - /// - protected bool m_waitingForObjectAsset; - - /// - /// Constructor - /// - public ArchiveWriteRequestPreparation(Scene scene, string savePath) - { - m_scene = scene; - m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress); - } - - /// - /// Constructor. - /// - /// - /// The stream to which to save data. - public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream) - { - m_scene = scene; - m_saveStream = saveStream; - } - - /// - /// The callback made when we request the asset for an object from the asset service. - /// - public void AssetRequestCallback(UUID assetID, AssetBase asset) - { - lock (this) - { - m_requestedObjectAsset = asset; - m_waitingForObjectAsset = false; - Monitor.Pulse(this); - } - } - - /// - /// Get an asset synchronously, potentially using an asynchronous callback. If the - /// asynchronous callback is used, we will wait for it to complete. - /// - /// - /// - protected AssetBase GetAsset(UUID uuid) - { - m_waitingForObjectAsset = true; - m_scene.AssetCache.GetAsset(uuid, AssetRequestCallback, true); - - // The asset cache callback can either - // - // 1. Complete on the same thread (if the asset is already in the cache) or - // 2. Come in via a different thread (if we need to go fetch it). - // - // The code below handles both these alternatives. - lock (this) - { - if (m_waitingForObjectAsset) - { - Monitor.Wait(this); - m_waitingForObjectAsset = false; - } - } - - return m_requestedObjectAsset; - } - - /// - /// Record the asset uuids embedded within the given script. - /// - /// - /// Dictionary in which to record the references - protected void GetScriptAssetUuids(UUID scriptUuid, IDictionary assetUuids) - { - AssetBase scriptAsset = GetAsset(scriptUuid); - - if (null != scriptAsset) - { - string script = Utils.BytesToString(scriptAsset.Data); - //m_log.DebugFormat("[ARCHIVER]: Script {0}", script); - MatchCollection uuidMatches = Util.UUIDPattern.Matches(script); - //m_log.DebugFormat("[ARCHIVER]: Found {0} matches in script", uuidMatches.Count); - - foreach (Match uuidMatch in uuidMatches) - { - UUID uuid = new UUID(uuidMatch.Value); - //m_log.DebugFormat("[ARCHIVER]: Recording {0} in script", uuid); - assetUuids[uuid] = 1; - } - } - } - - /// - /// Record the uuids referenced by the given wearable asset - /// - /// - /// Dictionary in which to record the references - protected void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary assetUuids) - { - AssetBase assetBase = GetAsset(wearableAssetUuid); - //m_log.Debug(new System.Text.ASCIIEncoding().GetString(bodypartAsset.Data)); - AssetWearable wearableAsset = new AssetBodypart(wearableAssetUuid, assetBase.Data); - wearableAsset.Decode(); - - //m_log.DebugFormat( - // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); - - foreach (UUID uuid in wearableAsset.Textures.Values) - { - //m_log.DebugFormat("[ARCHIVER]: Got bodypart uuid {0}", uuid); - assetUuids[uuid] = 1; - } - } - - /// - /// Get all the asset uuids associated with a given object. This includes both those directly associated with - /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained - /// within this object). - /// - /// - /// - protected void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary assetUuids) - { - AssetBase objectAsset = GetAsset(sceneObjectUuid); - - if (null != objectAsset) - { - string xml = Utils.BytesToString(objectAsset.Data); - SceneObjectGroup sog = new SceneObjectGroup(xml, true); - GetSceneObjectAssetUuids(sog, assetUuids); - } - } - - /// - /// Get all the asset uuids associated with a given object. This includes both those directly associated with - /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained - /// within this object). - /// - /// - /// - protected void GetSceneObjectAssetUuids(SceneObjectGroup sceneObject, IDictionary assetUuids) - { - m_log.DebugFormat( - "[ARCHIVER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); - - foreach (SceneObjectPart part in sceneObject.GetParts()) - { - //m_log.DebugFormat( - // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); - - try - { - Primitive.TextureEntry textureEntry = part.Shape.Textures; - - // Get the prim's default texture. This will be used for faces which don't have their own texture - assetUuids[textureEntry.DefaultTexture.TextureID] = 1; - - // XXX: Not a great way to iterate through face textures, but there's no - // other method available to tell how many faces there actually are - //int i = 0; - foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) - { - if (texture != null) - { - //m_log.DebugFormat("[ARCHIVER]: Got face {0}", i++); - assetUuids[texture.TextureID] = 1; - } - } - - // If the prim is a sculpt then preserve this information too - if (part.Shape.SculptTexture != UUID.Zero) - assetUuids[part.Shape.SculptTexture] = 1; - - // Now analyze this prim's inventory items to preserve all the uuids that they reference - foreach (TaskInventoryItem tii in part.TaskInventory.Values) - { - //m_log.DebugFormat("[ARCHIVER]: Analysing item asset type {0}", tii.Type); - - if (!assetUuids.ContainsKey(tii.AssetID)) - { - assetUuids[tii.AssetID] = 1; - - if ((int)AssetType.Bodypart == tii.Type || ((int)AssetType.Clothing == tii.Type)) - { - GetWearableAssetUuids(tii.AssetID, assetUuids); - } - else if ((int)AssetType.LSLText == tii.Type) - { - GetScriptAssetUuids(tii.AssetID, assetUuids); - } - else if ((int)AssetType.Object == tii.Type) - { - GetSceneObjectAssetUuids(tii.AssetID, assetUuids); - } - //else - //{ - //m_log.DebugFormat("[ARCHIVER]: Recording asset {0} in object {1}", tii.AssetID, part.UUID); - //} - } - } - } - catch (Exception e) - { - m_log.ErrorFormat("[ARCHIVER]: Failed to get part - {0}", e); - m_log.DebugFormat("[ARCHIVER]: Texture entry length for prim was {0} (min is 46)", part.Shape.TextureEntry.Length); - } - } - } - - /// - /// Archive the region requested. - /// - /// if there was an io problem with creating the file - public void ArchiveRegion() - { - Dictionary assetUuids = new Dictionary(); - - List entities = m_scene.GetEntities(); - List sceneObjects = new List(); - - // Filter entities so that we only have scene objects. - // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods - // end up having to do this - foreach (EntityBase entity in entities) - { - if (entity is SceneObjectGroup) - { - SceneObjectGroup sceneObject = (SceneObjectGroup)entity; - - if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) - sceneObjects.Add((SceneObjectGroup)entity); - } - } - - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - GetSceneObjectAssetUuids(sceneObject, assetUuids); - } - - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count); - - // Make sure that we also request terrain texture assets - RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; - - if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) - assetUuids[regionSettings.TerrainTexture1] = 1; - - if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) - assetUuids[regionSettings.TerrainTexture2] = 1; - - if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) - assetUuids[regionSettings.TerrainTexture3] = 1; - - if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) - assetUuids[regionSettings.TerrainTexture4] = 1; - - // Asynchronously request all the assets required to perform this archive operation - ArchiveWriteRequestExecution awre - = new ArchiveWriteRequestExecution( - sceneObjects, - m_scene.RequestModuleInterface(), - m_scene.RequestModuleInterface(), - m_scene, - m_saveStream); - - new AssetsRequest(assetUuids.Keys, m_scene.AssetCache, awre.ReceivedAllAssets).Execute(); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs deleted file mode 100644 index cd81169..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiverModule.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Serialiser; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// This module loads and saves OpenSimulator archives - /// - public class ArchiverModule : IRegionModule, IRegionArchiverModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - - public string Name { get { return "Archiver Module"; } } - - public bool IsSharedModule { get { return false; } } - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public void ArchiveRegion(string savePath) - { - m_log.InfoFormat( - "[ARCHIVER]: Writing archive for region {0} to {1}", m_scene.RegionInfo.RegionName, savePath); - - new ArchiveWriteRequestPreparation(m_scene, savePath).ArchiveRegion(); - } - - public void ArchiveRegion(Stream saveStream) - { - new ArchiveWriteRequestPreparation(m_scene, saveStream).ArchiveRegion(); - } - - public void DearchiveRegion(string loadPath) - { - m_log.InfoFormat( - "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath); - - new ArchiveReadRequest(m_scene, loadPath).DearchiveRegion(); - } - - public void DearchiveRegion(Stream loadStream) - { - new ArchiveReadRequest(m_scene, loadStream).DearchiveRegion(); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs deleted file mode 100644 index 36a60f3..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsArchiver.cs +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Xml; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Archives assets - /// - public class AssetsArchiver - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Archive assets - /// - protected IDictionary m_assets; - - public AssetsArchiver(IDictionary assets) - { - m_assets = assets; - } - - /// - /// Archive the assets given to this archiver to the given archive. - /// - /// - public void Archive(TarArchiveWriter archive) - { - //WriteMetadata(archive); - WriteData(archive); - } - - /// - /// Write an assets metadata file to the given archive - /// - /// - protected void WriteMetadata(TarArchiveWriter archive) - { - StringWriter sw = new StringWriter(); - XmlTextWriter xtw = new XmlTextWriter(sw); - - xtw.Formatting = Formatting.Indented; - xtw.WriteStartDocument(); - - xtw.WriteStartElement("assets"); - - foreach (UUID uuid in m_assets.Keys) - { - AssetBase asset = m_assets[uuid]; - - if (asset != null) - { - xtw.WriteStartElement("asset"); - - string extension = string.Empty; - - if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Metadata.Type)) - { - extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Metadata.Type]; - } - - xtw.WriteElementString("filename", uuid.ToString() + extension); - - xtw.WriteElementString("name", asset.Metadata.Name); - xtw.WriteElementString("description", asset.Metadata.Description); - xtw.WriteElementString("asset-type", asset.Metadata.Type.ToString()); - - xtw.WriteEndElement(); - } - } - - xtw.WriteEndElement(); - - xtw.WriteEndDocument(); - - archive.AddFile("assets.xml", sw.ToString()); - } - - /// - /// Write asset data files to the given archive - /// - /// - protected void WriteData(TarArchiveWriter archive) - { - // It appears that gtar, at least, doesn't need the intermediate directory entries in the tar - //archive.AddDir("assets"); - - foreach (UUID uuid in m_assets.Keys) - { - AssetBase asset = m_assets[uuid]; - - string extension = string.Empty; - - if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Metadata.Type)) - { - extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Metadata.Type]; - } - else - { - m_log.ErrorFormat( - "[ARCHIVER]: Unrecognized asset type {0} with uuid {1}. This asset will be saved but not reloaded", - asset.Metadata.Type, asset.Metadata.ID); - } - - archive.AddFile( - ArchiveConstants.ASSETS_PATH + uuid.ToString() + extension, - asset.Data); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs b/OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs deleted file mode 100644 index 95ff468..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsDearchiver.cs +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Xml; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Dearchives assets - /// - public class AssetsDearchiver - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); - - /// - /// Store for asset data we received before we get the metadata - /// - protected Dictionary m_assetDataAwaitingMetadata = new Dictionary(); - - /// - /// Asset metadata. Is null if asset metadata isn't yet available. - /// - protected Dictionary m_metadata; - - /// - /// Cache to which dearchived assets will be added - /// - protected IAssetCache m_cache; - - public AssetsDearchiver(IAssetCache cache) - { - m_cache = cache; - } - - /// - /// Add asset data to the dearchiver - /// - /// - /// - public void AddAssetData(string assetFilename, byte[] data) - { - if (null == m_metadata) - { - m_assetDataAwaitingMetadata[assetFilename] = data; - } - else - { - ResolveAssetData(assetFilename, data); - } - } - - /// - /// Add asset metadata xml - /// - /// - public void AddAssetMetadata(string xml) - { - m_metadata = new Dictionary(); - - StringReader sr = new StringReader(xml); - XmlTextReader reader = new XmlTextReader(sr); - - reader.ReadStartElement("assets"); - reader.Read(); - - while (reader.Name.Equals("asset")) - { - reader.Read(); - - AssetMetadata metadata = new AssetMetadata(); - - string filename = reader.ReadElementString("filename"); - m_log.DebugFormat("[DEARCHIVER]: Reading node {0}", filename); - - metadata.Name = reader.ReadElementString("name"); - metadata.Description = reader.ReadElementString("description"); - metadata.AssetType = Convert.ToSByte(reader.ReadElementString("asset-type")); - - m_metadata[filename] = metadata; - - // Read asset end tag - reader.ReadEndElement(); - - reader.Read(); - } - - m_log.DebugFormat("[DEARCHIVER]: Resolved {0} items of asset metadata", m_metadata.Count); - - ResolvePendingAssetData(); - } - - /// - /// Resolve asset data that we collected before receiving the metadata - /// - protected void ResolvePendingAssetData() - { - foreach (string filename in m_assetDataAwaitingMetadata.Keys) - { - ResolveAssetData(filename, m_assetDataAwaitingMetadata[filename]); - } - } - - /// - /// Resolve a new piece of asset data against stored metadata - /// - /// - /// - protected void ResolveAssetData(string assetPath, byte[] data) - { - // Right now we're nastily obtaining the UUID from the filename - string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); - - if (m_metadata.ContainsKey(filename)) - { - AssetMetadata metadata = m_metadata[filename]; - - if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(metadata.AssetType)) - { - string extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[metadata.AssetType]; - filename = filename.Remove(filename.Length - extension.Length); - } - - m_log.DebugFormat("[ARCHIVER]: Importing asset {0}", filename); - - AssetBase asset = new AssetBase(new UUID(filename), metadata.Name); - asset.Metadata.Description = metadata.Description; - asset.Metadata.Type = metadata.AssetType; - asset.Data = data; - - m_cache.AddAsset(asset); - } - else - { - m_log.ErrorFormat( - "[DEARCHIVER]: Tried to dearchive data with filename {0} without any corresponding metadata", - assetPath); - } - } - - /// - /// Metadata for an asset - /// - protected struct AssetMetadata - { - public string Name; - public string Description; - public sbyte AssetType; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs deleted file mode 100644 index b7fd170..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/AssetsRequest.cs +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Threading; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Encapsulate the asynchronous requests for the assets required for an archive operation - /// - class AssetsRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// uuids to request - /// - protected ICollection m_uuids; - - /// - /// Callback used when all the assets requested have been received. - /// - protected AssetsRequestCallback m_assetsRequestCallback; - - /// - /// Assets retrieved in this request - /// - protected Dictionary m_assets = new Dictionary(); - - /// - /// Maintain a list of assets that could not be found. This will be passed back to the requester. - /// - protected List m_notFoundAssetUuids = new List(); - - /// - /// Record the number of asset replies required so we know when we've finished - /// - private int m_repliesRequired; - - /// - /// Asset cache used to request the assets - /// - protected IAssetCache m_assetCache; - - protected internal AssetsRequest(ICollection uuids, IAssetCache assetCache, AssetsRequestCallback assetsRequestCallback) - { - m_uuids = uuids; - m_assetsRequestCallback = assetsRequestCallback; - m_assetCache = assetCache; - m_repliesRequired = uuids.Count; - } - - protected internal void Execute() - { - // We can stop here if there are no assets to fetch - if (m_repliesRequired == 0) - m_assetsRequestCallback(m_assets, m_notFoundAssetUuids); - - foreach (UUID uuid in m_uuids) - { - m_assetCache.GetAsset(uuid, AssetRequestCallback, true); - } - } - - /// - /// Called back by the asset cache when it has the asset - /// - /// - /// - public void AssetRequestCallback(UUID assetID, AssetBase asset) - { - if (asset != null) - m_assets[assetID] = asset; - else - m_notFoundAssetUuids.Add(assetID); - - //m_log.DebugFormat( - // "[ARCHIVER]: Received {0} assets and notification of {1} missing assets", m_assets.Count, m_notFoundAssetUuids.Count); - - if (m_assets.Count + m_notFoundAssetUuids.Count == m_repliesRequired) - { - // We want to stop using the asset cache thread asap as we now need to do the actual work of producing the archive - Thread newThread = new Thread(PerformAssetsRequestCallback); - newThread.Name = "OpenSimulator archiving thread post assets receipt"; - newThread.Start(); - } - } - - /// - /// Perform the callback on the original requester of the assets - /// - protected void PerformAssetsRequestCallback() - { - try - { - m_assetsRequestCallback(m_assets, m_notFoundAssetUuids); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[ARCHIVER]: Terminating archive creation since asset requster callback failed with {0}", e); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs b/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs deleted file mode 100644 index e12d0ec..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/RegionSettingsSerializer.cs +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Text; -using System.Xml; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Serialize and deserialize region settings for an archive file format. - /// - /// We didn't simply use automatic .NET serializagion for OpenSim.Framework.RegionSettings since this is really - /// a file format rather than an object serialization. - /// TODO: However, we could still have used separate non-framework classes here to read and write the xml - /// automatically rather than laboriously doing it by hand using XmlTextReader and Writer. Should switch to this - /// in the future. - public class RegionSettingsSerializer - { - protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - - /// - /// Deserialize region settings - /// - /// - /// - /// - public static RegionSettings Deserialize(byte[] serializedSettings) - { - return Deserialize(m_asciiEncoding.GetString(serializedSettings, 0, serializedSettings.Length)); - } - - /// - /// Deserialize region settings - /// - /// - /// - /// - public static RegionSettings Deserialize(string serializedSettings) - { - RegionSettings settings = new RegionSettings(); - - StringReader sr = new StringReader(serializedSettings); - XmlTextReader xtr = new XmlTextReader(sr); - - xtr.ReadStartElement("RegionSettings"); - - xtr.ReadStartElement("General"); - - while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) - { - switch (xtr.Name) - { - case "AllowDamage": - settings.AllowDamage = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "AllowLandResell": - settings.AllowLandResell = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "AllowLandJoinDivide": - settings.AllowLandJoinDivide = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "BlockFly": - settings.BlockFly = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "BlockLandShowInSearch": - settings.BlockShowInSearch = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "BlockTerraform": - settings.BlockTerraform = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "DisableCollisions": - settings.DisableCollisions = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "DisablePhysics": - settings.DisablePhysics = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "DisableScripts": - settings.DisableScripts = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "MaturityRating": - settings.Maturity = int.Parse(xtr.ReadElementContentAsString()); - break; - case "RestrictPushing": - settings.RestrictPushing = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "AgentLimit": - settings.AgentLimit = int.Parse(xtr.ReadElementContentAsString()); - break; - case "ObjectBonus": - settings.ObjectBonus = double.Parse(xtr.ReadElementContentAsString()); - break; - } - } - - xtr.ReadEndElement(); - xtr.ReadStartElement("GroundTextures"); - - while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) - { - switch (xtr.Name) - { - case "Texture1": - settings.TerrainTexture1 = UUID.Parse(xtr.ReadElementContentAsString()); - break; - case "Texture2": - settings.TerrainTexture2 = UUID.Parse(xtr.ReadElementContentAsString()); - break; - case "Texture3": - settings.TerrainTexture3 = UUID.Parse(xtr.ReadElementContentAsString()); - break; - case "Texture4": - settings.TerrainTexture4 = UUID.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationLowSW": - settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationLowNW": - settings.Elevation1NW = double.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationLowSE": - settings.Elevation1SE = double.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationLowNE": - settings.Elevation1NE = double.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationHighSW": - settings.Elevation1SW = double.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationHighNW": - settings.Elevation2NW = double.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationHighSE": - settings.Elevation2SE = double.Parse(xtr.ReadElementContentAsString()); - break; - case "ElevationHighNE": - settings.Elevation2NE = double.Parse(xtr.ReadElementContentAsString()); - break; - } - } - - xtr.ReadEndElement(); - xtr.ReadStartElement("Terrain"); - - while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) - { - switch (xtr.Name) - { - case "WaterHeight": - settings.WaterHeight = double.Parse(xtr.ReadElementContentAsString()); - break; - case "TerrainRaiseLimit": - settings.TerrainRaiseLimit = double.Parse(xtr.ReadElementContentAsString()); - break; - case "TerrainLowerLimit": - settings.TerrainLowerLimit = double.Parse(xtr.ReadElementContentAsString()); - break; - case "UseEstateSun": - settings.UseEstateSun = bool.Parse(xtr.ReadElementContentAsString()); - break; - case "FixedSun": - settings.FixedSun = bool.Parse(xtr.ReadElementContentAsString()); - break; - } - } - - xtr.Close(); - sr.Close(); - - return settings; - } - - public static string Serialize(RegionSettings settings) - { - StringWriter sw = new StringWriter(); - XmlTextWriter xtw = new XmlTextWriter(sw); - xtw.Formatting = Formatting.Indented; - xtw.WriteStartDocument(); - - xtw.WriteStartElement("RegionSettings"); - - xtw.WriteStartElement("General"); - xtw.WriteElementString("AllowDamage", settings.AllowDamage.ToString()); - xtw.WriteElementString("AllowLandResell", settings.AllowLandResell.ToString()); - xtw.WriteElementString("AllowLandJoinDivide", settings.AllowLandJoinDivide.ToString()); - xtw.WriteElementString("BlockFly", settings.BlockFly.ToString()); - xtw.WriteElementString("BlockLandShowInSearch", settings.BlockShowInSearch.ToString()); - xtw.WriteElementString("BlockTerraform", settings.BlockTerraform.ToString()); - xtw.WriteElementString("DisableCollisions", settings.DisableCollisions.ToString()); - xtw.WriteElementString("DisablePhysics", settings.DisablePhysics.ToString()); - xtw.WriteElementString("DisableScripts", settings.DisableScripts.ToString()); - xtw.WriteElementString("MaturityRating", settings.Maturity.ToString()); - xtw.WriteElementString("RestrictPushing", settings.RestrictPushing.ToString()); - xtw.WriteElementString("AgentLimit", settings.AgentLimit.ToString()); - xtw.WriteElementString("ObjectBonus", settings.ObjectBonus.ToString()); - xtw.WriteEndElement(); - - xtw.WriteStartElement("GroundTextures"); - xtw.WriteElementString("Texture1", settings.TerrainTexture1.ToString()); - xtw.WriteElementString("Texture2", settings.TerrainTexture2.ToString()); - xtw.WriteElementString("Texture3", settings.TerrainTexture3.ToString()); - xtw.WriteElementString("Texture4", settings.TerrainTexture4.ToString()); - xtw.WriteElementString("ElevationLowSW", settings.Elevation1SW.ToString()); - xtw.WriteElementString("ElevationLowNW", settings.Elevation1NW.ToString()); - xtw.WriteElementString("ElevationLowSE", settings.Elevation1SE.ToString()); - xtw.WriteElementString("ElevationLowNE", settings.Elevation1NE.ToString()); - xtw.WriteElementString("ElevationHighSW", settings.Elevation2SW.ToString()); - xtw.WriteElementString("ElevationHighNW", settings.Elevation2NW.ToString()); - xtw.WriteElementString("ElevationHighSE", settings.Elevation2SE.ToString()); - xtw.WriteElementString("ElevationHighNE", settings.Elevation2NE.ToString()); - xtw.WriteEndElement(); - - xtw.WriteStartElement("Terrain"); - xtw.WriteElementString("WaterHeight", settings.WaterHeight.ToString()); - xtw.WriteElementString("TerrainRaiseLimit", settings.TerrainRaiseLimit.ToString()); - xtw.WriteElementString("TerrainLowerLimit", settings.TerrainLowerLimit.ToString()); - xtw.WriteElementString("UseEstateSun", settings.UseEstateSun.ToString()); - xtw.WriteElementString("FixedSun", settings.FixedSun.ToString()); - // XXX: Need to expose interface to get sun phase information from sun module - // xtw.WriteStartElement("SunPhase", - xtw.WriteEndElement(); - - xtw.WriteEndElement(); - - xtw.Close(); - sw.Close(); - - return sw.ToString(); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs b/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs deleted file mode 100644 index 3862546..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveReader.cs +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Reflection; -using System.Text; -using log4net; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Temporary code to do the bare minimum required to read a tar archive for our purposes - /// - public class TarArchiveReader - { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public enum TarEntryType - { - TYPE_UNKNOWN = 0, - TYPE_NORMAL_FILE = 1, - TYPE_HARD_LINK = 2, - TYPE_SYMBOLIC_LINK = 3, - TYPE_CHAR_SPECIAL = 4, - TYPE_BLOCK_SPECIAL = 5, - TYPE_DIRECTORY = 6, - TYPE_FIFO = 7, - TYPE_CONTIGUOUS_FILE = 8, - } - - protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - - /// - /// Binary reader for the underlying stream - /// - protected BinaryReader m_br; - - /// - /// Used to trim off null chars - /// - protected char[] m_nullCharArray = new char[] { '\0' }; - - /// - /// Generate a tar reader which reads from the given stream. - /// - /// - public TarArchiveReader(Stream s) - { - m_br = new BinaryReader(s); - } - - /// - /// Read the next entry in the tar file. - /// - /// - /// the data for the entry. Returns null if there are no more entries - public byte[] ReadEntry(out string filePath, out TarEntryType entryType) - { - filePath = String.Empty; - entryType = TarEntryType.TYPE_UNKNOWN; - TarHeader header = ReadHeader(); - - if (null == header) - return null; - - entryType = header.EntryType; - filePath = header.FilePath; - byte[] data = m_br.ReadBytes(header.FileSize); - - //m_log.DebugFormat("[TAR ARCHIVE READER]: filePath {0}, fileSize {1}", filePath, header.FileSize); - - // Read the rest of the empty padding in the 512 byte block - if (header.FileSize % 512 != 0) - { - int paddingLeft = 512 - (header.FileSize % 512); - - //m_log.DebugFormat("[TAR ARCHIVE READER]: Reading {0} padding bytes", paddingLeft); - - m_br.ReadBytes(paddingLeft); - } - - return data; - } - - /// - /// Read the next 512 byte chunk of data as a tar header. - /// - /// A tar header struct. null if we have reached the end of the archive. - protected TarHeader ReadHeader() - { - byte[] header = m_br.ReadBytes(512); - - // If we've reached the end of the archive we'll be in null block territory, which means - // the next byte will be 0 - if (header[0] == 0) - return null; - - TarHeader tarHeader = new TarHeader(); - - tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100); - tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray); - tarHeader.FileSize = ConvertOctalBytesToDecimal(header, 124, 11); - - switch (header[156]) - { - case 0: - tarHeader.EntryType = TarEntryType.TYPE_NORMAL_FILE; - break; - case (byte)'0': - tarHeader.EntryType = TarEntryType.TYPE_NORMAL_FILE; - break; - case (byte)'1': - tarHeader.EntryType = TarEntryType.TYPE_HARD_LINK; - break; - case (byte)'2': - tarHeader.EntryType = TarEntryType.TYPE_SYMBOLIC_LINK; - break; - case (byte)'3': - tarHeader.EntryType = TarEntryType.TYPE_CHAR_SPECIAL; - break; - case (byte)'4': - tarHeader.EntryType = TarEntryType.TYPE_BLOCK_SPECIAL; - break; - case (byte)'5': - tarHeader.EntryType = TarEntryType.TYPE_DIRECTORY; - break; - case (byte)'6': - tarHeader.EntryType = TarEntryType.TYPE_FIFO; - break; - case (byte)'7': - tarHeader.EntryType = TarEntryType.TYPE_CONTIGUOUS_FILE; - break; - } - - return tarHeader; - } - - public void Close() - { - m_br.Close(); - } - - /// - /// Convert octal bytes to a decimal representation - /// - /// - /// - public static int ConvertOctalBytesToDecimal(byte[] bytes, int startIndex, int count) - { - string oString = m_asciiEncoding.GetString(bytes, startIndex, count); - - int d = 0; - - foreach (char c in oString) - { - d <<= 3; - d |= c - '0'; - } - - return d; - } - } - - public class TarHeader - { - public string FilePath; - public int FileSize; - public TarArchiveReader.TarEntryType EntryType; - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs b/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs deleted file mode 100644 index 8fd247c..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/TarArchiveWriter.cs +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Reflection; -using log4net; - -namespace OpenSim.Region.Environment.Modules.World.Archiver -{ - /// - /// Temporary code to produce a tar archive in tar v7 format - /// - public class TarArchiveWriter - { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Dictionary m_files = new Dictionary(); - - protected static ASCIIEncoding m_asciiEncoding = new ASCIIEncoding(); - - /// - /// Add a directory to the tar archive. We can only handle one path level right now! - /// - /// - public void AddDir(string dirName) - { - // Directories are signalled by a final / - if (!dirName.EndsWith("/")) - dirName += "/"; - - AddFile(dirName, new byte[0]); - } - - /// - /// Add a file to the tar archive - /// - /// - /// - public void AddFile(string filePath, string data) - { - AddFile(filePath, m_asciiEncoding.GetBytes(data)); - } - - /// - /// Add a file to the tar archive - /// - /// - /// - public void AddFile(string filePath, byte[] data) - { - m_files[filePath] = data; - } - - /// - /// Write the raw tar archive data to a stream. The stream will be closed on completion. - /// - /// Stream to which to write the data - /// - public void WriteTar(Stream s) - { - BinaryWriter bw = new BinaryWriter(s); - - foreach (string filePath in m_files.Keys) - { - byte[] header = new byte[512]; - byte[] data = m_files[filePath]; - - // file path field (100) - byte[] nameBytes = m_asciiEncoding.GetBytes(filePath); - int nameSize = (nameBytes.Length >= 100) ? 100 : nameBytes.Length; - Array.Copy(nameBytes, header, nameSize); - - // file mode (8) - byte[] modeBytes = m_asciiEncoding.GetBytes("0000777"); - Array.Copy(modeBytes, 0, header, 100, 7); - - // owner user id (8) - byte[] ownerIdBytes = m_asciiEncoding.GetBytes("0000764"); - Array.Copy(ownerIdBytes, 0, header, 108, 7); - - // group user id (8) - byte[] groupIdBytes = m_asciiEncoding.GetBytes("0000764"); - Array.Copy(groupIdBytes, 0, header, 116, 7); - - // file size in bytes (12) - int fileSize = data.Length; - //m_log.DebugFormat("[TAR ARCHIVE WRITER]: File size of {0} is {1}", filePath, fileSize); - - byte[] fileSizeBytes = ConvertDecimalToPaddedOctalBytes(fileSize, 11); - - Array.Copy(fileSizeBytes, 0, header, 124, 11); - - // last modification time (12) - byte[] lastModTimeBytes = m_asciiEncoding.GetBytes("11017037332"); - Array.Copy(lastModTimeBytes, 0, header, 136, 11); - - // link indicator (1) - //header[156] = m_asciiEncoding.GetBytes("0")[0]; - if (filePath.EndsWith("/")) - { - header[156] = m_asciiEncoding.GetBytes("5")[0]; - } - else - { - header[156] = 0; - } - - Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 329, 7); - Array.Copy(m_asciiEncoding.GetBytes("0000000"), 0, header, 337, 7); - - // check sum for header block (8) [calculated last] - Array.Copy(m_asciiEncoding.GetBytes(" "), 0, header, 148, 8); - - int checksum = 0; - foreach (byte b in header) - { - checksum += b; - } - - //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Decimal header checksum is {0}", checksum); - - byte[] checkSumBytes = ConvertDecimalToPaddedOctalBytes(checksum, 6); - - Array.Copy(checkSumBytes, 0, header, 148, 6); - - header[154] = 0; - - // Write out header - bw.Write(header); - - // Write out data - bw.Write(data); - - if (data.Length % 512 != 0) - { - int paddingRequired = 512 - (data.Length % 512); - - //m_log.DebugFormat("[TAR ARCHIVE WRITER]: Padding data with {0} bytes", paddingRequired); - - byte[] padding = new byte[paddingRequired]; - bw.Write(padding); - } - } - - //m_log.Debug("[TAR ARCHIVE WRITER]: Writing final consecutive 0 blocks"); - - // Write two consecutive 0 blocks to end the archive - byte[] finalZeroPadding = new byte[1024]; - bw.Write(finalZeroPadding); - - bw.Flush(); - bw.Close(); - } - - public static byte[] ConvertDecimalToPaddedOctalBytes(int d, int padding) - { - string oString = ""; - - while (d > 0) - { - oString = Convert.ToString((byte)'0' + d & 7) + oString; - d >>= 3; - } - - while (oString.Length < padding) - { - oString = "0" + oString; - } - - byte[] oBytes = m_asciiEncoding.GetBytes(oString); - - return oBytes; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs deleted file mode 100644 index e265252..0000000 --- a/OpenSim/Region/Environment/Modules/World/Archiver/Tests/ArchiverTests.cs +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Threading; -using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.World.Archiver; -using OpenSim.Region.Environment.Modules.World.Serialiser; -using OpenSim.Region.Environment.Modules.World.Terrain; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common.Setup; - -namespace OpenSim.Region.Environment.Modules.World.Archiver.Tests -{ - [TestFixture] - public class ArchiverTests - { - private EventWaitHandle m_waitHandle = new AutoResetEvent(false); - - private void SaveCompleted(string errorMessage) - { - m_waitHandle.Set(); - } - - /// - /// Test saving a V0.2 OpenSim Region Archive. - /// - [Test] - public void TestSaveOarV0p2() - { - log4net.Config.XmlConfigurator.Configure(); - - ArchiverModule archiverModule = new ArchiverModule(); - SerialiserModule serialiserModule = new SerialiserModule(); - TerrainModule terrainModule = new TerrainModule(); - - Scene scene = SceneSetupHelpers.SetupScene(); - SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); - - SceneObjectPart part1; - - // Create and add prim 1 - { - string partName = "My Little Pony"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000015"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Name = partName; - - scene.AddNewSceneObject(new SceneObjectGroup(part1), false); - } - - SceneObjectPart part2; - - // Create and add prim 2 - { - string partName = "Action Man"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000016"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); - Vector3 groupPosition = new Vector3(90, 80, 70); - Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); - Vector3 offsetPosition = new Vector3(20, 25, 30); - - part2 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part2.Name = partName; - - scene.AddNewSceneObject(new SceneObjectGroup(part2), false); - } - - MemoryStream archiveWriteStream = new MemoryStream(); - - scene.EventManager.OnOarFileSaved += SaveCompleted; - archiverModule.ArchiveRegion(archiveWriteStream); - m_waitHandle.WaitOne(60000, true); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - bool gotControlFile = false; - bool gotObject1File = false; - bool gotObject2File = false; - string expectedObject1FileName = string.Format( - "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", - part1.Name, - Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), - part1.UUID); - string expectedObject2FileName = string.Format( - "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", - part2.Name, - Math.Round(part2.GroupPosition.X), Math.Round(part2.GroupPosition.Y), Math.Round(part2.GroupPosition.Z), - part2.UUID); - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - if (ArchiveConstants.CONTROL_FILE_PATH == filePath) - { - gotControlFile = true; - } - else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - string fileName = filePath.Remove(0, ArchiveConstants.OBJECTS_PATH.Length); - - if (fileName.StartsWith(part1.Name)) - { - Assert.That(fileName, Is.EqualTo(expectedObject1FileName)); - gotObject1File = true; - } - else if (fileName.StartsWith(part2.Name)) - { - Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); - gotObject2File = true; - } - } - } - - Assert.That(gotControlFile, Is.True, "No control file in archive"); - Assert.That(gotObject1File, Is.True, "No object1 file in archive"); - Assert.That(gotObject2File, Is.True, "No object2 file in archive"); - - // TODO: Test presence of more files and contents of files. - } - - /// - /// Test loading a V0.2 OpenSim Region Archive. Does not yet do what it says on the tin. - /// - [Test] - public void TestLoadOarV0p2() - { - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(); - - tar.AddFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile()); - tar.WriteTar(archiveWriteStream); - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - ArchiverModule archiverModule = new ArchiverModule(); - - Scene scene = SceneSetupHelpers.SetupScene(); - SceneSetupHelpers.SetupSceneModules(scene, archiverModule); - - archiverModule.DearchiveRegion(archiveReadStream); - - // TODO: Okay, so nothing is tested yet apart from the fact that it doesn't blow up - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs deleted file mode 100644 index 6b74c83..0000000 --- a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs +++ /dev/null @@ -1,1012 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Threading; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Estate -{ - public class EstateManagementModule : IEstateModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private delegate void LookupUUIDS(List uuidLst); - - private Scene m_scene; - - private EstateTerrainXferHandler TerrainUploader = null; - - #region Packet Data Responders - - private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) - { - uint sun = 0; - - if (!m_scene.RegionInfo.EstateSettings.UseGlobalTime) - sun=(uint)(m_scene.RegionInfo.EstateSettings.SunPosition*1024.0) + 0x1800; - UUID estateOwner; - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - estateOwner = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - estateOwner = m_scene.RegionInfo.MasterAvatarAssignedUUID; - - if (m_scene.Permissions.IsGod(remote_client.AgentId)) - estateOwner = remote_client.AgentId; - - remote_client.SendDetailedEstateData(invoice, - m_scene.RegionInfo.EstateSettings.EstateName, - m_scene.RegionInfo.EstateSettings.EstateID, - m_scene.RegionInfo.EstateSettings.ParentEstateID, - GetEstateFlags(), - sun, - m_scene.RegionInfo.RegionSettings.Covenant, - m_scene.RegionInfo.EstateSettings.AbuseEmail, - estateOwner); - - remote_client.SendEstateManagersList(invoice, - m_scene.RegionInfo.EstateSettings.EstateManagers, - m_scene.RegionInfo.EstateSettings.EstateID); - - remote_client.SendBannedUserList(invoice, - m_scene.RegionInfo.EstateSettings.EstateBans, - m_scene.RegionInfo.EstateSettings.EstateID); - } - - private void estateSetRegionInfoHandler(bool blockTerraform, bool noFly, bool allowDamage, bool blockLandResell, int maxAgents, float objectBonusFactor, - int matureLevel, bool restrictPushObject, bool allowParcelChanges) - { - if (blockTerraform) - m_scene.RegionInfo.RegionSettings.BlockTerraform = true; - else - m_scene.RegionInfo.RegionSettings.BlockTerraform = false; - - if (noFly) - m_scene.RegionInfo.RegionSettings.BlockFly = true; - else - m_scene.RegionInfo.RegionSettings.BlockFly = false; - - if (allowDamage) - m_scene.RegionInfo.RegionSettings.AllowDamage = true; - else - m_scene.RegionInfo.RegionSettings.AllowDamage = false; - - if (blockLandResell) - m_scene.RegionInfo.RegionSettings.AllowLandResell = false; - else - m_scene.RegionInfo.RegionSettings.AllowLandResell = true; - - m_scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; - - m_scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; - - if (matureLevel <= 13) - m_scene.RegionInfo.RegionSettings.Maturity = 0; - else - m_scene.RegionInfo.RegionSettings.Maturity = 1; - - if (restrictPushObject) - m_scene.RegionInfo.RegionSettings.RestrictPushing = true; - else - m_scene.RegionInfo.RegionSettings.RestrictPushing = false; - - if (allowParcelChanges) - m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide = true; - else - m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide = false; - - m_scene.RegionInfo.RegionSettings.Save(); - - sendRegionInfoPacketToAll(); - } - - public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int corner, UUID texture) - { - if (texture == UUID.Zero) - return; - - switch (corner) - { - case 0: - m_scene.RegionInfo.RegionSettings.TerrainTexture1 = texture; - break; - case 1: - m_scene.RegionInfo.RegionSettings.TerrainTexture2 = texture; - break; - case 2: - m_scene.RegionInfo.RegionSettings.TerrainTexture3 = texture; - break; - case 3: - m_scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; - break; - } - m_scene.RegionInfo.RegionSettings.Save(); - } - - public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue) - { - switch (corner) - { - case 0: - m_scene.RegionInfo.RegionSettings.Elevation1SW = lowValue; - m_scene.RegionInfo.RegionSettings.Elevation2SW = highValue; - break; - case 1: - m_scene.RegionInfo.RegionSettings.Elevation1NW = lowValue; - m_scene.RegionInfo.RegionSettings.Elevation2NW = highValue; - break; - case 2: - m_scene.RegionInfo.RegionSettings.Elevation1SE = lowValue; - m_scene.RegionInfo.RegionSettings.Elevation2SE = highValue; - break; - case 3: - m_scene.RegionInfo.RegionSettings.Elevation1NE = lowValue; - m_scene.RegionInfo.RegionSettings.Elevation2NE = highValue; - break; - } - m_scene.RegionInfo.RegionSettings.Save(); - } - - private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) - { - sendRegionHandshakeToAll(); - } - - public void setRegionTerrainSettings(float WaterHeight, - float TerrainRaiseLimit, float TerrainLowerLimit, - bool UseEstateSun, bool UseFixedSun, float SunHour, - bool UseGlobal, bool EstateFixedSun, float EstateSunHour) - { - // Water Height - m_scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight; - - // Terraforming limits - m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit = TerrainRaiseLimit; - m_scene.RegionInfo.RegionSettings.TerrainLowerLimit = TerrainLowerLimit; - - // Time of day / fixed sun - m_scene.RegionInfo.RegionSettings.UseEstateSun = UseEstateSun; - m_scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun; - m_scene.RegionInfo.RegionSettings.SunPosition = SunHour; - - m_scene.EventManager.TriggerEstateToolsTimeUpdate(m_scene.RegionInfo.RegionHandle, UseFixedSun, UseEstateSun, SunHour); - - //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString()); - //m_log.Debug("[ESTATE]: SunHour: " + SunHour.ToString()); - - sendRegionInfoPacketToAll(); - m_scene.RegionInfo.RegionSettings.Save(); - } - - private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) - { - m_scene.Restart(timeInSeconds); - } - - private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID) - { - m_scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; - m_scene.RegionInfo.RegionSettings.Save(); - } - - private void handleEstateAccessDeltaRequest(IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user) - { - // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc. - - if (user == m_scene.RegionInfo.EstateSettings.EstateOwner) - return; // never process EO - if (user == m_scene.RegionInfo.MasterAvatarAssignedUUID) - return; // never process owner - - switch (estateAccessType) - { - case 64: - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) - { - EstateBan[] banlistcheck = m_scene.RegionInfo.EstateSettings.EstateBans; - - bool alreadyInList = false; - - for (int i = 0; i < banlistcheck.Length; i++) - { - if (user == banlistcheck[i].bannedUUID) - { - alreadyInList = true; - break; - } - - } - if (!alreadyInList) - { - - EstateBan item = new EstateBan(); - - item.bannedUUID = user; - item.estateID = m_scene.RegionInfo.EstateSettings.EstateID; - item.bannedIP = "0.0.0.0"; - item.bannedIPHostMask = "0.0.0.0"; - - m_scene.RegionInfo.EstateSettings.AddBan(item); - m_scene.RegionInfo.EstateSettings.Save(); - - ScenePresence s = m_scene.GetScenePresence(user); - if (s != null) - { - if (!s.IsChildAgent) - { - s.ControllingClient.SendTeleportLocationStart(); - m_scene.TeleportClientHome(user, s.ControllingClient); - } - } - - } - else - { - remote_client.SendAlertMessage("User is already on the region ban list"); - } - //m_scene.RegionInfo.regionBanlist.Add(Manager(user); - remote_client.SendBannedUserList(invoice, m_scene.RegionInfo.EstateSettings.EstateBans, m_scene.RegionInfo.EstateSettings.EstateID); - } - else - { - remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); - } - break; - case 128: - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) - { - EstateBan[] banlistcheck = m_scene.RegionInfo.EstateSettings.EstateBans; - - bool alreadyInList = false; - EstateBan listitem = null; - - for (int i = 0; i < banlistcheck.Length; i++) - { - if (user == banlistcheck[i].bannedUUID) - { - alreadyInList = true; - listitem = banlistcheck[i]; - break; - } - - } - if (alreadyInList && listitem != null) - { - m_scene.RegionInfo.EstateSettings.RemoveBan(listitem.bannedUUID); - m_scene.RegionInfo.EstateSettings.Save(); - } - else - { - remote_client.SendAlertMessage("User is not on the region ban list"); - } - //m_scene.RegionInfo.regionBanlist.Add(Manager(user); - remote_client.SendBannedUserList(invoice, m_scene.RegionInfo.EstateSettings.EstateBans, m_scene.RegionInfo.EstateSettings.EstateID); - } - else - { - remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); - } - break; - case 256: - - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) - { - m_scene.RegionInfo.EstateSettings.AddEstateManager(user); - m_scene.RegionInfo.EstateSettings.Save(); - remote_client.SendEstateManagersList(invoice, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID); - } - else - { - remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); - } - - break; - case 512: - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) - { - m_scene.RegionInfo.EstateSettings.RemoveEstateManager(user); - m_scene.RegionInfo.EstateSettings.Save(); - - remote_client.SendEstateManagersList(invoice, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID); - } - else - { - remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); - } - break; - - default: - - m_log.ErrorFormat("EstateOwnerMessage: Unknown EstateAccessType requested in estateAccessDelta: {0}", estateAccessType.ToString()); - break; - } - } - - private void SendSimulatorBlueBoxMessage( - IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) - { - IDialogModule dm = m_scene.RequestModuleInterface(); - - if (dm != null) - dm.SendNotificationToUsersInRegion(senderID, senderName, message); - } - - private void SendEstateBlueBoxMessage( - IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) - { - IDialogModule dm = m_scene.RequestModuleInterface(); - - if (dm != null) - dm.SendNotificationToUsersInEstate(senderID, senderName, message); - } - - private void handleEstateDebugRegionRequest(IClientAPI remote_client, UUID invoice, UUID senderID, bool scripted, bool collisionEvents, bool physics) - { - if (physics) - m_scene.RegionInfo.RegionSettings.DisablePhysics = true; - else - m_scene.RegionInfo.RegionSettings.DisablePhysics = false; - - if (scripted) - m_scene.RegionInfo.RegionSettings.DisableScripts = true; - else - m_scene.RegionInfo.RegionSettings.DisableScripts = false; - - if (collisionEvents) - m_scene.RegionInfo.RegionSettings.DisableCollisions = true; - else - m_scene.RegionInfo.RegionSettings.DisableCollisions = false; - - - m_scene.RegionInfo.RegionSettings.Save(); - - m_scene.SetSceneCoreDebug(scripted, collisionEvents, physics); - } - - private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) - { - if (prey != UUID.Zero) - { - ScenePresence s = m_scene.GetScenePresence(prey); - if (s != null) - { - s.ControllingClient.SendTeleportLocationStart(); - m_scene.TeleportClientHome(prey, s.ControllingClient); - } - } - } - - private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID) - { - // Get a fresh list that will not change as people get teleported away - List prescences = m_scene.GetScenePresences(); - foreach (ScenePresence p in prescences) - { - if (p.UUID != senderID) - { - // make sure they are still there, we could be working down a long list - ScenePresence s = m_scene.GetScenePresence(p.UUID); - if (s != null) - { - // Also make sure they are actually in the region - if (!s.IsChildAgent) - { - s.ControllingClient.SendTeleportLocationStart(); - m_scene.TeleportClientHome(s.UUID, s.ControllingClient); - } - } - } - } - } - private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) - { - if (TerrainUploader != null) - { - lock (TerrainUploader) - { - if (XferID == TerrainUploader.XferID) - { - remoteClient.OnXferReceive -= TerrainUploader.XferReceive; - remoteClient.OnAbortXfer -= AbortTerrainXferHandler; - TerrainUploader.TerrainUploadDone -= HandleTerrainApplication; - - TerrainUploader = null; - remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); - } - } - } - - } - private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) - { - lock (TerrainUploader) - { - remoteClient.OnXferReceive -= TerrainUploader.XferReceive; - remoteClient.OnAbortXfer -= AbortTerrainXferHandler; - TerrainUploader.TerrainUploadDone -= HandleTerrainApplication; - - TerrainUploader = null; - } - remoteClient.SendAlertMessage("Terrain Upload Complete. Loading...."); - OpenSim.Region.Environment.Modules.World.Terrain.ITerrainModule terr = m_scene.RequestModuleInterface(); - - if (terr != null) - { - m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + m_scene.RegionInfo.RegionName); - if (System.IO.File.Exists(Util.dataDir() + "/terrain.raw")) - { - System.IO.File.Delete(Util.dataDir() + "/terrain.raw"); - } - try - { - System.IO.FileStream input = new System.IO.FileStream(Util.dataDir() + "/terrain.raw", System.IO.FileMode.CreateNew); - input.Write(terrainData, 0, terrainData.Length); - input.Close(); - } - catch (System.IO.IOException e) - { - m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); - remoteClient.SendAlertMessage("There was an IO Exception loading your terrain. Please check free space"); - - return; - } - catch (System.Security.SecurityException e) - { - m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); - remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive"); - - return; - } - catch (System.UnauthorizedAccessException e) - { - m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); - remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive"); - - return; - } - - - - - try - { - terr.LoadFromFile(Util.dataDir() + "/terrain.raw"); - remoteClient.SendAlertMessage("Your terrain was loaded. Give it a minute or two to apply"); - } - catch (Exception e) - { - m_log.ErrorFormat("[TERRAIN]: Error loading a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); - remoteClient.SendAlertMessage("There was a general error loading your terrain. Please fix the terrain file and try again"); - } - - } - else - { - remoteClient.SendAlertMessage("Unable to apply terrain. Cannot get an instance of the terrain module"); - } - - - - } - - private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) - { - - if (TerrainUploader == null) - { - - TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName); - lock (TerrainUploader) - { - remote_client.OnXferReceive += TerrainUploader.XferReceive; - remote_client.OnAbortXfer += AbortTerrainXferHandler; - TerrainUploader.TerrainUploadDone += HandleTerrainApplication; - } - TerrainUploader.RequestStartXfer(remote_client); - - } - else - { - remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); - } - - } - private void handleTerrainRequest(IClientAPI remote_client, string clientFileName) - { - // Save terrain here - OpenSim.Region.Environment.Modules.World.Terrain.ITerrainModule terr = m_scene.RequestModuleInterface(); - - if (terr != null) - { - m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + m_scene.RegionInfo.RegionName); - if (System.IO.File.Exists(Util.dataDir() + "/terrain.raw")) - { - System.IO.File.Delete(Util.dataDir() + "/terrain.raw"); - } - terr.SaveToFile(Util.dataDir() + "/terrain.raw"); - - System.IO.FileStream input = new System.IO.FileStream(Util.dataDir() + "/terrain.raw", System.IO.FileMode.Open); - byte[] bdata = new byte[input.Length]; - input.Read(bdata, 0, (int)input.Length); - remote_client.SendAlertMessage("Terrain file written, starting download..."); - m_scene.XferManager.AddNewFile("terrain.raw", bdata); - // Tell client about it - m_log.Warn("[CLIENT]: Sending Terrain to " + remote_client.Name); - remote_client.SendInitiateDownload("terrain.raw", clientFileName); - } - } - - private void HandleRegionInfoRequest(IClientAPI remote_client) - { - RegionInfoForEstateMenuArgs args = new RegionInfoForEstateMenuArgs(); - args.billableFactor = m_scene.RegionInfo.EstateSettings.BillableFactor; - args.estateID = m_scene.RegionInfo.EstateSettings.EstateID; - args.maxAgents = (byte)m_scene.RegionInfo.RegionSettings.AgentLimit; - args.objectBonusFactor = (float)m_scene.RegionInfo.RegionSettings.ObjectBonus; - args.parentEstateID = m_scene.RegionInfo.EstateSettings.ParentEstateID; - args.pricePerMeter = m_scene.RegionInfo.EstateSettings.PricePerMeter; - args.redirectGridX = m_scene.RegionInfo.EstateSettings.RedirectGridX; - args.redirectGridY = m_scene.RegionInfo.EstateSettings.RedirectGridY; - args.regionFlags = GetRegionFlags(); - byte mature = 13; - if (m_scene.RegionInfo.RegionSettings.Maturity == 1) - mature = 21; - args.simAccess = mature; - - args.sunHour = (float)m_scene.RegionInfo.RegionSettings.SunPosition; - args.terrainLowerLimit = (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit; - args.terrainRaiseLimit = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; - args.useEstateSun = m_scene.RegionInfo.RegionSettings.UseEstateSun; - args.waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; - args.simName = m_scene.RegionInfo.RegionName; - - remote_client.SendRegionInfoToEstateMenu(args); - } - - private void HandleEstateCovenantRequest(IClientAPI remote_client) - { - remote_client.SendEstateCovenantInformation(m_scene.RegionInfo.RegionSettings.Covenant); - } - - private void HandleLandStatRequest(int parcelID, uint reportType, uint requestFlags, string filter, IClientAPI remoteClient) - { - Dictionary SceneData = new Dictionary(); - List uuidNameLookupList = new List(); - - if (reportType == 1) - { - SceneData = m_scene.PhysicsScene.GetTopColliders(); - } - else if (reportType == 0) - { - SceneData = m_scene.m_sceneGraph.GetTopScripts(); - } - - List SceneReport = new List(); - lock (SceneData) - { - foreach (uint obj in SceneData.Keys) - { - SceneObjectPart prt = m_scene.GetSceneObjectPart(obj); - if (prt != null) - { - if (prt.ParentGroup != null) - { - SceneObjectGroup sog = prt.ParentGroup; - if (sog != null) - { - LandStatReportItem lsri = new LandStatReportItem(); - lsri.LocationX = sog.AbsolutePosition.X; - lsri.LocationY = sog.AbsolutePosition.Y; - lsri.LocationZ = sog.AbsolutePosition.Z; - lsri.Score = SceneData[obj]; - lsri.TaskID = sog.UUID; - lsri.TaskLocalID = sog.LocalId; - lsri.TaskName = sog.GetPartName(obj); - if (m_scene.CommsManager.UUIDNameCachedTest(sog.OwnerID)) - { - lsri.OwnerName = m_scene.CommsManager.UUIDNameRequestString(sog.OwnerID); - } - else - { - lsri.OwnerName = "waiting"; - lock (uuidNameLookupList) - uuidNameLookupList.Add(sog.OwnerID); - } - - if (filter.Length != 0) - { - if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter))) - { - } - else - { - continue; - } - } - - SceneReport.Add(lsri); - } - } - } - - } - } - remoteClient.SendLandStatReply(reportType, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray()); - - if (uuidNameLookupList.Count > 0) - LookupUUID(uuidNameLookupList); - } - - private void LookupUUIDSCompleted(IAsyncResult iar) - { - LookupUUIDS icon = (LookupUUIDS)iar.AsyncState; - icon.EndInvoke(iar); - } - private void LookupUUID(List uuidLst) - { - LookupUUIDS d = LookupUUIDsAsync; - - d.BeginInvoke(uuidLst, - LookupUUIDSCompleted, - d); - } - private void LookupUUIDsAsync(List uuidLst) - { - UUID[] uuidarr = new UUID[0]; - - lock (uuidLst) - { - uuidarr = uuidLst.ToArray(); - } - - for (int i = 0; i < uuidarr.Length; i++) - { - // string lookupname = m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]); - m_scene.CommsManager.UUIDNameRequestString(uuidarr[i]); - // we drop it. It gets cached though... so we're ready for the next request. - } - } - #endregion - - #region Outgoing Packets - - public void sendRegionInfoPacketToAll() - { - List avatars = m_scene.GetAvatars(); - - for (int i = 0; i < avatars.Count; i++) - { - HandleRegionInfoRequest(avatars[i].ControllingClient); ; - } - } - - public void sendRegionHandshake(IClientAPI remoteClient) - { - RegionHandshakeArgs args = new RegionHandshakeArgs(); - - args.isEstateManager = m_scene.RegionInfo.EstateSettings.IsEstateManager(remoteClient.AgentId); - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && m_scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId) - args.isEstateManager = true; - - args.billableFactor = m_scene.RegionInfo.EstateSettings.BillableFactor; - args.terrainStartHeight0 = (float)m_scene.RegionInfo.RegionSettings.Elevation1SW; - args.terrainHeightRange0 = (float)m_scene.RegionInfo.RegionSettings.Elevation2SW; - args.terrainStartHeight1 = (float)m_scene.RegionInfo.RegionSettings.Elevation1NW; - args.terrainHeightRange1 = (float)m_scene.RegionInfo.RegionSettings.Elevation2NW; - args.terrainStartHeight2 = (float)m_scene.RegionInfo.RegionSettings.Elevation1SE; - args.terrainHeightRange2 = (float)m_scene.RegionInfo.RegionSettings.Elevation2SE; - args.terrainStartHeight3 = (float)m_scene.RegionInfo.RegionSettings.Elevation1NE; - args.terrainHeightRange3 = (float)m_scene.RegionInfo.RegionSettings.Elevation2NE; - byte mature = 13; - if (m_scene.RegionInfo.RegionSettings.Maturity == 1) - mature = 21; - args.simAccess = mature; - args.waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; - - args.regionFlags = GetRegionFlags(); - args.regionName = m_scene.RegionInfo.RegionName; - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - args.SimOwner = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - args.SimOwner = m_scene.RegionInfo.MasterAvatarAssignedUUID; - - // Fudge estate owner - //if (m_scene.Permissions.IsGod(remoteClient.AgentId)) - // args.SimOwner = remoteClient.AgentId; - - args.terrainBase0 = UUID.Zero; - args.terrainBase1 = UUID.Zero; - args.terrainBase2 = UUID.Zero; - args.terrainBase3 = UUID.Zero; - args.terrainDetail0 = m_scene.RegionInfo.RegionSettings.TerrainTexture1; - args.terrainDetail1 = m_scene.RegionInfo.RegionSettings.TerrainTexture2; - args.terrainDetail2 = m_scene.RegionInfo.RegionSettings.TerrainTexture3; - args.terrainDetail3 = m_scene.RegionInfo.RegionSettings.TerrainTexture4; - - remoteClient.SendRegionHandshake(m_scene.RegionInfo,args); - } - - public void sendRegionHandshakeToAll() - { - m_scene.Broadcast(sendRegionHandshake); - } - - public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2) - { - if (parms2 == 0) - { - m_scene.RegionInfo.EstateSettings.UseGlobalTime = true; - m_scene.RegionInfo.EstateSettings.SunPosition = 0.0; - } - else - { - m_scene.RegionInfo.EstateSettings.UseGlobalTime = false; - m_scene.RegionInfo.EstateSettings.SunPosition = (double)(parms2 - 0x1800)/1024.0; - } - - if ((parms1 & 0x00000010) != 0) - m_scene.RegionInfo.EstateSettings.FixedSun = true; - else - m_scene.RegionInfo.EstateSettings.FixedSun = false; - - if ((parms1 & 0x00008000) != 0) - m_scene.RegionInfo.EstateSettings.PublicAccess = true; - else - m_scene.RegionInfo.EstateSettings.PublicAccess = false; - - if ((parms1 & 0x10000000) != 0) - m_scene.RegionInfo.EstateSettings.AllowVoice = true; - else - m_scene.RegionInfo.EstateSettings.AllowVoice = false; - - if ((parms1 & 0x00100000) != 0) - m_scene.RegionInfo.EstateSettings.AllowDirectTeleport = true; - else - m_scene.RegionInfo.EstateSettings.AllowDirectTeleport = false; - - if ((parms1 & 0x00800000) != 0) - m_scene.RegionInfo.EstateSettings.DenyAnonymous = true; - else - m_scene.RegionInfo.EstateSettings.DenyAnonymous = false; - - if ((parms1 & 0x01000000) != 0) - m_scene.RegionInfo.EstateSettings.DenyIdentified = true; - else - m_scene.RegionInfo.EstateSettings.DenyIdentified = false; - - if ((parms1 & 0x02000000) != 0) - m_scene.RegionInfo.EstateSettings.DenyTransacted = true; - else - m_scene.RegionInfo.EstateSettings.DenyTransacted = false; - - if ((parms1 & 0x40000000) != 0) - m_scene.RegionInfo.EstateSettings.DenyMinors = true; - else - m_scene.RegionInfo.EstateSettings.DenyMinors = false; - - m_scene.RegionInfo.EstateSettings.Save(); - - float sun = (float)m_scene.RegionInfo.RegionSettings.SunPosition; - if (m_scene.RegionInfo.RegionSettings.UseEstateSun) - { - sun = (float)m_scene.RegionInfo.EstateSettings.SunPosition; - if (m_scene.RegionInfo.EstateSettings.UseGlobalTime) - sun = m_scene.EventManager.GetSunLindenHour(); - } - - m_scene.EventManager.TriggerEstateToolsTimeUpdate( - m_scene.RegionInfo.RegionHandle, - m_scene.RegionInfo.EstateSettings.FixedSun || - m_scene.RegionInfo.RegionSettings.FixedSun, - m_scene.RegionInfo.RegionSettings.UseEstateSun, sun); - - sendDetailedEstateData(remoteClient, invoice); - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - m_scene.EventManager.OnNewClient += EventManager_OnNewClient; - m_scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight; - } - - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "EstateManagementModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region Other Functions - - public void changeWaterHeight(float height) - { - setRegionTerrainSettings(height, - (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit, - (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit, - m_scene.RegionInfo.RegionSettings.UseEstateSun, - m_scene.RegionInfo.RegionSettings.FixedSun, - (float)m_scene.RegionInfo.RegionSettings.SunPosition, - m_scene.RegionInfo.EstateSettings.UseGlobalTime, - m_scene.RegionInfo.EstateSettings.FixedSun, - (float)m_scene.RegionInfo.EstateSettings.SunPosition); - - sendRegionInfoPacketToAll(); - } - - #endregion - - private void EventManager_OnNewClient(IClientAPI client) - { - client.OnDetailedEstateDataRequest += sendDetailedEstateData; - client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler; -// client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture; - client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture; - client.OnSetEstateTerrainTextureHeights += setEstateTerrainTextureHeights; - client.OnCommitEstateTerrainTextureRequest += handleCommitEstateTerrainTextureRequest; - client.OnSetRegionTerrainSettings += setRegionTerrainSettings; - client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; - client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; - client.OnEstateChangeInfo += handleEstateChangeInfo; - client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; - client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; - client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; - client.OnEstateDebugRegionRequest += handleEstateDebugRegionRequest; - client.OnEstateTeleportOneUserHomeRequest += handleEstateTeleportOneUserHomeRequest; - client.OnEstateTeleportAllUsersHomeRequest += handleEstateTeleportAllUsersHomeRequest; - client.OnRequestTerrain += handleTerrainRequest; - client.OnUploadTerrain += handleUploadTerrain; - - client.OnRegionInfoRequest += HandleRegionInfoRequest; - client.OnEstateCovenantRequest += HandleEstateCovenantRequest; - client.OnLandStatRequest += HandleLandStatRequest; - sendRegionHandshake(client); - } - - public uint GetRegionFlags() - { - RegionFlags flags = RegionFlags.None; - - // Fully implemented - // - if (m_scene.RegionInfo.RegionSettings.AllowDamage) - flags |= RegionFlags.AllowDamage; - if (m_scene.RegionInfo.RegionSettings.BlockTerraform) - flags |= RegionFlags.BlockTerraform; - if (!m_scene.RegionInfo.RegionSettings.AllowLandResell) - flags |= RegionFlags.BlockLandResell; - if (m_scene.RegionInfo.RegionSettings.DisableCollisions) - flags |= RegionFlags.SkipCollisions; - if (m_scene.RegionInfo.RegionSettings.DisableScripts) - flags |= RegionFlags.SkipScripts; - if (m_scene.RegionInfo.RegionSettings.DisablePhysics) - flags |= RegionFlags.SkipPhysics; - if (m_scene.RegionInfo.RegionSettings.BlockFly) - flags |= RegionFlags.NoFly; - if (m_scene.RegionInfo.RegionSettings.RestrictPushing) - flags |= RegionFlags.RestrictPushObject; - if (m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide) - flags |= RegionFlags.AllowParcelChanges; - if (m_scene.RegionInfo.RegionSettings.BlockShowInSearch) - flags |= (RegionFlags)(1 << 29); - - if (m_scene.RegionInfo.RegionSettings.FixedSun) - flags |= RegionFlags.SunFixed; - if (m_scene.RegionInfo.RegionSettings.Sandbox) - flags |= RegionFlags.Sandbox; - - // Fudge these to always on, so the menu options activate - // - flags |= RegionFlags.AllowLandmark; - flags |= RegionFlags.AllowSetHome; - - // TODO: SkipUpdateInterestList - - // Omitted - // - // Omitted: NullLayer (what is that?) - // Omitted: SkipAgentAction (what does it do?) - - return (uint)flags; - } - - public uint GetEstateFlags() - { - RegionFlags flags = RegionFlags.None; - - if (m_scene.RegionInfo.EstateSettings.FixedSun) - flags |= RegionFlags.SunFixed; - if (m_scene.RegionInfo.EstateSettings.PublicAccess) - flags |= (RegionFlags.PublicAllowed | - RegionFlags.ExternallyVisible); - if (m_scene.RegionInfo.EstateSettings.AllowVoice) - flags |= RegionFlags.AllowVoice; - if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) - flags |= RegionFlags.AllowDirectTeleport; - if (m_scene.RegionInfo.EstateSettings.DenyAnonymous) - flags |= RegionFlags.DenyAnonymous; - if (m_scene.RegionInfo.EstateSettings.DenyIdentified) - flags |= RegionFlags.DenyIdentified; - if (m_scene.RegionInfo.EstateSettings.DenyTransacted) - flags |= RegionFlags.DenyTransacted; - if (m_scene.RegionInfo.EstateSettings.AbuseEmailToEstateOwner) - flags |= RegionFlags.AbuseEmailToEstateOwner; - if (m_scene.RegionInfo.EstateSettings.BlockDwell) - flags |= RegionFlags.BlockDwell; - if (m_scene.RegionInfo.EstateSettings.EstateSkipScripts) - flags |= RegionFlags.EstateSkipScripts; - if (m_scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) - flags |= RegionFlags.ResetHomeOnTeleport; - if (m_scene.RegionInfo.EstateSettings.TaxFree) - flags |= RegionFlags.TaxFree; - if (m_scene.RegionInfo.EstateSettings.DenyMinors) - flags |= (RegionFlags)(1 << 30); - - return (uint)flags; - } - - public bool IsManager(UUID avatarID) - { - if (avatarID == m_scene.RegionInfo.MasterAvatarAssignedUUID) - return true; - if (avatarID == m_scene.RegionInfo.EstateSettings.EstateOwner) - return true; - - List ems = new List(m_scene.RegionInfo.EstateSettings.EstateManagers); - if (ems.Contains(avatarID)) - return true; - - return false; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs deleted file mode 100644 index 267178e..0000000 --- a/OpenSim/Region/Environment/Modules/World/Estate/EstateTerrainXferHandler.cs +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Reflection; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Scenes; - - -namespace OpenSim.Region.Environment.Modules.World.Estate -{ - - public class EstateTerrainXferHandler - { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private AssetBase m_asset; - - public delegate void TerrainUploadComplete(string name, byte[] filedata, IClientAPI remoteClient); - - public event TerrainUploadComplete TerrainUploadDone; - - //private string m_description = String.Empty; - //private string m_name = String.Empty; - //private UUID TransactionID = UUID.Zero; - private sbyte type = 0; - - public ulong mXferID; - private TerrainUploadComplete handlerTerrainUploadDone; - - public EstateTerrainXferHandler(IClientAPI pRemoteClient, string pClientFilename) - { - - m_asset = new AssetBase(); - m_asset.Metadata.FullID = UUID.Zero; - m_asset.Metadata.Type = type; - m_asset.Data = new byte[0]; - m_asset.Metadata.Name = pClientFilename; - m_asset.Metadata.Description = "empty"; - m_asset.Metadata.Local = true; - m_asset.Metadata.Temporary = true; - - } - - public ulong XferID - { - get { return mXferID; } - } - - public void RequestStartXfer(IClientAPI pRemoteClient) - { - mXferID = Util.GetNextXferID(); - pRemoteClient.SendXferRequest(mXferID, m_asset.Metadata.Type, m_asset.Metadata.FullID, 0, Utils.StringToBytes(m_asset.Metadata.Name)); - } - - /// - /// Process transfer data received from the client. - /// - /// - /// - /// - public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) - { - if (mXferID == xferID) - { - if (m_asset.Data.Length > 1) - { - byte[] destinationArray = new byte[m_asset.Data.Length + data.Length]; - Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length); - Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length); - m_asset.Data = destinationArray; - } - else - { - byte[] buffer2 = new byte[data.Length - 4]; - Array.Copy(data, 4, buffer2, 0, data.Length - 4); - m_asset.Data = buffer2; - } - - remoteClient.SendConfirmXfer(xferID, packetID); - - if ((packetID & 0x80000000) != 0) - { - SendCompleteMessage(remoteClient); - - } - } - } - - public void SendCompleteMessage(IClientAPI remoteClient) - { - handlerTerrainUploadDone = TerrainUploadDone; - if (handlerTerrainUploadDone != null) - { - handlerTerrainUploadDone(m_asset.Metadata.Name, m_asset.Data, remoteClient); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs b/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs deleted file mode 100644 index 76555d2..0000000 --- a/OpenSim/Region/Environment/Modules/World/Land/LandChannel.cs +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Land -{ - public class LandChannel : ILandChannel - { - #region Constants - - //Land types set with flags in ParcelOverlay. - //Only one of these can be used. - public const float BAN_LINE_SAFETY_HIEGHT = 100; - public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000 - public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000 - - //RequestResults (I think these are right, they seem to work): - public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land - public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land - - //ParcelSelectObjects - public const int LAND_SELECT_OBJECTS_GROUP = 4; - public const int LAND_SELECT_OBJECTS_OTHER = 8; - public const int LAND_SELECT_OBJECTS_OWNER = 2; - public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101 - public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100 - public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010 - public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001 - public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011 - public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000 - - //These are other constants. Yay! - public const int START_LAND_LOCAL_ID = 1; - - #endregion - - private readonly Scene m_scene; - private readonly LandManagementModule m_landManagementModule; - - public LandChannel(Scene scene, LandManagementModule landManagementMod) - { - m_scene = scene; - m_landManagementModule = landManagementMod; - } - - #region ILandChannel Members - - - /// - /// Get the land object at the specified point - /// - /// Value between 0 - 256 on the x axis of the point - /// Value between 0 - 256 on the y axis of the point - /// Land object at the point supplied - public ILandObject GetLandObject(float x_float, float y_float) - { - if (m_landManagementModule != null) - { - return m_landManagementModule.GetLandObject(x_float, y_float); - } - ILandObject obj = new LandObject(UUID.Zero, false, m_scene); - obj.landData.Name = "NO LAND"; - return obj; - } - - public ILandObject GetLandObject(int x, int y) - { - if (m_landManagementModule != null) - { - return m_landManagementModule.GetLandObject(x, y); - } - ILandObject obj = new LandObject(UUID.Zero, false, m_scene); - obj.landData.Name = "NO LAND"; - return obj; - } - - public List AllParcels() - { - if (m_landManagementModule != null) - { - return m_landManagementModule.AllParcels(); - } - - return new List(); - } - - public List ParcelsNearPoint(Vector3 position) - { - if (m_landManagementModule != null) - { - return m_landManagementModule.ParcelsNearPoint(position); - } - - return new List(); - } - - public bool IsLandPrimCountTainted() - { - if (m_landManagementModule != null) - { - return m_landManagementModule.IsLandPrimCountTainted(); - } - - return false; - } - - public bool IsForcefulBansAllowed() - { - if (m_landManagementModule != null) - { - return m_landManagementModule.AllowedForcefulBans; - } - - return false; - } - - public void UpdateLandObject(int localID, LandData data) - { - if (m_landManagementModule != null) - { - m_landManagementModule.UpdateLandObject(localID, data); - } - } - public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) - { - if (m_landManagementModule != null) - { - m_landManagementModule.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient); - } - } - - public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) - { - if (m_landManagementModule != null) - { - m_landManagementModule.setParcelObjectMaxOverride(overrideDel); - } - } - - public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) - { - if (m_landManagementModule != null) - { - m_landManagementModule.setSimulatorObjectMaxOverride(overrideDel); - } - } - - public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) - { - if (m_landManagementModule != null) - { - m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs deleted file mode 100644 index 58176e4..0000000 --- a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs +++ /dev/null @@ -1,1347 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Communications.Capabilities; -using OpenSim.Region.Physics.Manager; -using Caps = OpenSim.Framework.Communications.Capabilities.Caps; - -namespace OpenSim.Region.Environment.Modules.World.Land -{ - // used for caching - internal class ExtendedLandData { - public LandData landData; - public ulong regionHandle; - public uint x, y; - } - - public class LandManagementModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly string remoteParcelRequestPath = "0009/"; - - private LandChannel landChannel; - private Scene m_scene; - - private readonly int[,] m_landIDList = new int[64, 64]; - private readonly Dictionary m_landList = new Dictionary(); - - private bool m_landPrimCountTainted; - private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; - - private bool m_allowedForcefulBans = true; - - // caches ExtendedLandData - private Cache parcelInfoCache; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - m_landIDList.Initialize(); - landChannel = new LandChannel(scene, this); - - parcelInfoCache = new Cache(); - parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache - parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0); - - m_scene.EventManager.OnParcelPrimCountAdd += AddPrimToLandPrimCounts; - m_scene.EventManager.OnParcelPrimCountUpdate += UpdateLandPrimCounts; - m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(handleAvatarChangingParcel); - m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(handleAnyClientMovement); - m_scene.EventManager.OnValidateLandBuy += handleLandValidationRequest; - m_scene.EventManager.OnLandBuy += handleLandBuyRequest; - m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); - m_scene.EventManager.OnSignificantClientMovement += handleSignificantClientMovement; - m_scene.EventManager.OnObjectBeingRemovedFromScene += RemovePrimFromLandPrimCounts; - - m_scene.EventManager.OnNoticeNoLandDataFromStorage += this.NoLandDataFromStorage; - m_scene.EventManager.OnIncomingLandDataFromStorage += this.IncomingLandObjectsFromStorage; - m_scene.EventManager.OnSetAllowForcefulBan += this.SetAllowedForcefulBans; - m_scene.EventManager.OnRequestParcelPrimCountUpdate += this.PerformParcelPrimCountUpdate; - m_scene.EventManager.OnParcelPrimCountTainted += this.SetPrimsTainted; - m_scene.EventManager.OnRegisterCaps += this.OnRegisterCaps; - - lock (m_scene) - { - m_scene.LandChannel = (ILandChannel) landChannel; - } - } - - void EventManager_OnNewClient(IClientAPI client) - { - //Register some client events - client.OnParcelPropertiesRequest += new ParcelPropertiesRequest(handleParcelPropertiesRequest); - client.OnParcelDivideRequest += new ParcelDivideRequest(handleParcelDivideRequest); - client.OnParcelJoinRequest += new ParcelJoinRequest(handleParcelJoinRequest); - client.OnParcelPropertiesUpdateRequest += new ParcelPropertiesUpdateRequest(handleParcelPropertiesUpdateRequest); - client.OnParcelSelectObjects += new ParcelSelectObjects(handleParcelSelectObjectsRequest); - client.OnParcelObjectOwnerRequest += new ParcelObjectOwnerRequest(handleParcelObjectOwnersRequest); - client.OnParcelAccessListRequest += new ParcelAccessListRequest(handleParcelAccessRequest); - client.OnParcelAccessListUpdateRequest += new ParcelAccessListUpdateRequest(handleParcelAccessUpdateRequest); - client.OnParcelAbandonRequest += new ParcelAbandonRequest(handleParcelAbandonRequest); - client.OnParcelGodForceOwner += new ParcelGodForceOwner(handleParcelGodForceOwner); - client.OnParcelReclaim += new ParcelReclaim(handleParcelReclaim); - client.OnParcelInfoRequest += new ParcelInfoRequest(handleParcelInfo); - client.OnParcelDwellRequest += new ParcelDwellRequest(handleParcelDwell); - if (m_scene.Entities.ContainsKey(client.AgentId)) - { - SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true); - SendParcelOverlay(client); - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "LandManagementModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region Parcel Add/Remove/Get/Create - - public void SetAllowedForcefulBans(bool forceful) - { - AllowedForcefulBans = forceful; - } - - public void UpdateLandObject(int local_id, LandData data) - { - LandData newData = data.Copy(); - newData.LocalID = local_id; - - lock (m_landList) - { - if (m_landList.ContainsKey(local_id)) - { - m_landList[local_id].landData = newData; - m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]); - } - } - } - - public bool AllowedForcefulBans - { - get { return m_allowedForcefulBans; } - set { m_allowedForcefulBans = value; } - } - - /// - /// Resets the sim to the default land object (full sim piece of land owned by the default user) - /// - public void ResetSimLandObjects() - { - //Remove all the land objects in the sim and add a blank, full sim land object set to public - lock (m_landList) - { - m_landList.Clear(); - m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; - m_landIDList.Initialize(); - } - - ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); - - fullSimParcel.setLandBitmap(fullSimParcel.getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - fullSimParcel.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - fullSimParcel.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; - fullSimParcel.landData.ClaimDate = Util.UnixTimeSinceEpoch(); - AddLandObject(fullSimParcel); - } - - public List AllParcels() - { - lock (m_landList) - { - return new List(m_landList.Values); - } - } - - public List ParcelsNearPoint(Vector3 position) - { - List parcelsNear = new List(); - for (int x = -4; x <= 4; x += 4) - { - for (int y = -4; y <= 4; y += 4) - { - ILandObject check = GetLandObject(position.X + x, position.Y + y); - if (check != null) - { - if (!parcelsNear.Contains(check)) - { - parcelsNear.Add(check); - } - } - } - } - - return parcelsNear; - } - - public void SendYouAreBannedNotice(ScenePresence avatar) - { - if (AllowedForcefulBans) - { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because you are banned. Please go away."); - - avatar.PhysicsActor.Position = - new PhysicsVector(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y, - avatar.lastKnownAllowedPosition.Z); - avatar.PhysicsActor.Velocity = new PhysicsVector(0, 0, 0); - } - else - { - avatar.ControllingClient.SendAlertMessage( - "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!"); - } - } - - public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, UUID regionID) - { - if (m_scene.RegionInfo.RegionID == regionID) - { - ILandObject parcelAvatarIsEntering; - lock (m_landList) - { - parcelAvatarIsEntering = m_landList[localLandID]; - } - - if (parcelAvatarIsEntering != null) - { - if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) - { - if (parcelAvatarIsEntering.isBannedFromLand(avatar.UUID)) - { - SendYouAreBannedNotice(avatar); - } - else if (parcelAvatarIsEntering.isRestrictedFromLand(avatar.UUID)) - { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!)."); - } - else - { - avatar.sentMessageAboutRestrictedParcelFlyingDown = true; - } - } - else - { - avatar.sentMessageAboutRestrictedParcelFlyingDown = true; - } - } - } - } - - public void SendOutNearestBanLine(IClientAPI avatar) - { - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence presence in avatars) - { - if (presence.UUID == avatar.AgentId) - { - List checkLandParcels = ParcelsNearPoint(presence.AbsolutePosition); - foreach (ILandObject checkBan in checkLandParcels) - { - if (checkBan.isBannedFromLand(avatar.AgentId)) - { - checkBan.sendLandProperties((int)ParcelStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar); - return; //Only send one - } - if (checkBan.isRestrictedFromLand(avatar.AgentId)) - { - checkBan.sendLandProperties((int)ParcelStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar); - return; //Only send one - } - } - return; - } - } - } - - public void SendLandUpdate(ScenePresence avatar, bool force) - { - ILandObject over = GetLandObject((int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), - (int)Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); - - if (over != null) - { - if (force) - { - if (!avatar.IsChildAgent) - { - over.sendLandUpdateToClient(avatar.ControllingClient); - m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID, - m_scene.RegionInfo.RegionID); - } - } - - if (avatar.currentParcelUUID != over.landData.GlobalID) - { - if (!avatar.IsChildAgent) - { - over.sendLandUpdateToClient(avatar.ControllingClient); - avatar.currentParcelUUID = over.landData.GlobalID; - m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.LocalID, - m_scene.RegionInfo.RegionID); - } - } - } - } - - public void SendLandUpdate(ScenePresence avatar) - { - SendLandUpdate(avatar, false); - } - - public void handleSignificantClientMovement(IClientAPI remote_client) - { - ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId); - - if (clientAvatar != null) - { - SendLandUpdate(clientAvatar); - SendOutNearestBanLine(remote_client); - ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); - if (parcel != null) - { - if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && - clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) - { - handleAvatarChangingParcel(clientAvatar, parcel.landData.LocalID, m_scene.RegionInfo.RegionID); - //They are going below the safety line! - if (!parcel.isBannedFromLand(clientAvatar.UUID)) - { - clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false; - } - } - else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && - parcel.isBannedFromLand(clientAvatar.UUID)) - { - SendYouAreBannedNotice(clientAvatar); - } - } - } - } - - public void handleAnyClientMovement(ScenePresence avatar) - //Like handleSignificantClientMovement, but called with an AgentUpdate regardless of distance. - { - ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); - if (over != null) - { - if (!over.isBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT) - { - avatar.lastKnownAllowedPosition = - new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); - } - } - } - - - public void handleParcelAccessRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID, - int landLocalID, IClientAPI remote_client) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(landLocalID, out land); - } - - if (land != null) - { - m_landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client); - } - } - - public void handleParcelAccessUpdateRequest(UUID agentID, UUID sessionID, uint flags, int landLocalID, - List entries, - IClientAPI remote_client) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(landLocalID, out land); - } - - if (land != null) - { - if (agentID == land.landData.OwnerID) - { - land.updateAccessList(flags, entries, remote_client); - } - } - else - { - m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID); - } - } - - /// - /// Creates a basic Parcel object without an owner (a zeroed key) - /// - /// - public ILandObject CreateBaseLand() - { - return new LandObject(UUID.Zero, false, m_scene); - } - - /// - /// Adds a land object to the stored list and adds them to the landIDList to what they own - /// - /// The land object being added - public ILandObject AddLandObject(ILandObject land) - { - ILandObject new_land = land.Copy(); - - lock (m_landList) - { - int newLandLocalID = ++m_lastLandLocalID; - new_land.landData.LocalID = newLandLocalID; - - bool[,] landBitmap = new_land.getLandBitmap(); - for (int x = 0; x < 64; x++) - { - for (int y = 0; y < 64; y++) - { - if (landBitmap[x, y]) - { - m_landIDList[x, y] = newLandLocalID; - } - } - } - - m_landList.Add(newLandLocalID, new_land); - } - - new_land.forceUpdateLandInfo(); - m_scene.EventManager.TriggerLandObjectAdded(new_land); - return new_land; - } - - /// - /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList - /// - /// Land.localID of the peice of land to remove. - public void removeLandObject(int local_id) - { - lock (m_landList) - { - for (int x = 0; x < 64; x++) - { - for (int y = 0; y < 64; y++) - { - if (m_landIDList[x, y] == local_id) - { - m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}", - local_id, x, y); - return; - //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); - } - } - } - - m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].landData.GlobalID); - m_landList.Remove(local_id); - } - } - - private void performFinalLandJoin(ILandObject master, ILandObject slave) - { - bool[,] landBitmapSlave = slave.getLandBitmap(); - lock (m_landList) - { - for (int x = 0; x < 64; x++) - { - for (int y = 0; y < 64; y++) - { - if (landBitmapSlave[x, y]) - { - m_landIDList[x, y] = master.landData.LocalID; - } - } - } - } - - removeLandObject(slave.landData.LocalID); - UpdateLandObject(master.landData.LocalID, master.landData); - } - - public ILandObject GetLandObject(int parcelLocalID) - { - lock (m_landList) - { - if (m_landList.ContainsKey(parcelLocalID)) - { - return m_landList[parcelLocalID]; - } - } - return null; - } - - /// - /// Get the land object at the specified point - /// - /// Value between 0 - 256 on the x axis of the point - /// Value between 0 - 256 on the y axis of the point - /// Land object at the point supplied - public ILandObject GetLandObject(float x_float, float y_float) - { - int x; - int y; - - try - { - x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0)); - y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0)); - } - catch (OverflowException) - { - return null; - } - - if (x >= 64 || y >= 64 || x < 0 || y < 0) - { - return null; - } - lock (m_landList) - { - // Corner case. If an autoreturn happens during sim startup - // we will come here with the list uninitialized - // - if (m_landList.ContainsKey(m_landIDList[x, y])) - return m_landList[m_landIDList[x, y]]; - return null; - } - } - - public ILandObject GetLandObject(int x, int y) - { - if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) - { - // These exceptions here will cause a lot of complaints from the users specifically because - // they happen every time at border crossings - throw new Exception("Error: Parcel not found at point " + x + ", " + y); - } - lock (m_landIDList) - { - return m_landList[m_landIDList[x / 4, y / 4]]; - } - } - - #endregion - - #region Parcel Modification - - public void ResetAllLandPrimCounts() - { - lock (m_landList) - { - foreach (LandObject p in m_landList.Values) - { - p.resetLandPrimCounts(); - } - } - } - - public void SetPrimsTainted() - { - m_landPrimCountTainted = true; - } - - public bool IsLandPrimCountTainted() - { - return m_landPrimCountTainted; - } - - public void AddPrimToLandPrimCounts(SceneObjectGroup obj) - { - Vector3 position = obj.AbsolutePosition; - ILandObject landUnderPrim = GetLandObject(position.X, position.Y); - if (landUnderPrim != null) - { - landUnderPrim.addPrimToCount(obj); - } - } - - public void RemovePrimFromLandPrimCounts(SceneObjectGroup obj) - { - - lock (m_landList) - { - foreach (LandObject p in m_landList.Values) - { - p.removePrimFromCount(obj); - } - } - } - - public void FinalizeLandPrimCountUpdate() - { - //Get Simwide prim count for owner - Dictionary> landOwnersAndParcels = new Dictionary>(); - lock (m_landList) - { - foreach (LandObject p in m_landList.Values) - { - if (!landOwnersAndParcels.ContainsKey(p.landData.OwnerID)) - { - List tempList = new List(); - tempList.Add(p); - landOwnersAndParcels.Add(p.landData.OwnerID, tempList); - } - else - { - landOwnersAndParcels[p.landData.OwnerID].Add(p); - } - } - } - - foreach (UUID owner in landOwnersAndParcels.Keys) - { - int simArea = 0; - int simPrims = 0; - foreach (LandObject p in landOwnersAndParcels[owner]) - { - simArea += p.landData.Area; - simPrims += p.landData.OwnerPrims + p.landData.OtherPrims + p.landData.GroupPrims + - p.landData.SelectedPrims; - } - - foreach (LandObject p in landOwnersAndParcels[owner]) - { - p.landData.SimwideArea = simArea; - p.landData.SimwidePrims = simPrims; - } - } - } - - public void UpdateLandPrimCounts() - { - ResetAllLandPrimCounts(); - foreach (EntityBase obj in m_scene.Entities) - { - if (obj != null) - { - if ((obj is SceneObjectGroup) && !obj.IsDeleted && !((SceneObjectGroup) obj).IsAttachment) - { - m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup) obj); - } - } - } - FinalizeLandPrimCountUpdate(); - m_landPrimCountTainted = false; - } - - public void PerformParcelPrimCountUpdate() - { - ResetAllLandPrimCounts(); - m_scene.EventManager.TriggerParcelPrimCountUpdate(); - FinalizeLandPrimCountUpdate(); - m_landPrimCountTainted = false; - } - - /// - /// Subdivides a piece of land - /// - /// West Point - /// South Point - /// East Point - /// North Point - /// UUID of user who is trying to subdivide - /// Returns true if successful - private void subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) - { - //First, lets loop through the points and make sure they are all in the same peice of land - //Get the land object at start - - ILandObject startLandObject = GetLandObject(start_x, start_y); - - if (startLandObject == null) return; - - //Loop through the points - try - { - int totalX = end_x - start_x; - int totalY = end_y - start_y; - for (int y = 0; y < totalY; y++) - { - for (int x = 0; x < totalX; x++) - { - ILandObject tempLandObject = GetLandObject(start_x + x, start_y + y); - if (tempLandObject == null) return; - if (tempLandObject != startLandObject) return; - } - } - } - catch (Exception) - { - return; - } - - //If we are still here, then they are subdividing within one piece of land - //Check owner - if (!m_scene.Permissions.CanEditParcel(attempting_user_id, startLandObject)) - { - return; - } - - //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) - ILandObject newLand = startLandObject.Copy(); - newLand.landData.Name = "Subdivision of " + newLand.landData.Name; - newLand.landData.GlobalID = UUID.Random(); - - newLand.setLandBitmap(newLand.getSquareLandBitmap(start_x, start_y, end_x, end_y)); - - //Now, lets set the subdivision area of the original to false - int startLandObjectIndex = startLandObject.landData.LocalID; - lock (m_landList) - { - m_landList[startLandObjectIndex].setLandBitmap( - newLand.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false)); - m_landList[startLandObjectIndex].forceUpdateLandInfo(); - } - - SetPrimsTainted(); - - //Now add the new land object - ILandObject result = AddLandObject(newLand); - UpdateLandObject(startLandObject.landData.LocalID, startLandObject.landData); - result.sendLandUpdateToAvatarsOverMe(); - } - - /// - /// Join 2 land objects together - /// - /// x value in first piece of land - /// y value in first piece of land - /// x value in second peice of land - /// y value in second peice of land - /// UUID of the avatar trying to join the land objects - /// Returns true if successful - private void join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) - { - end_x -= 4; - end_y -= 4; - - List selectedLandObjects = new List(); - int stepYSelected; - for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4) - { - int stepXSelected; - for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4) - { - ILandObject p = GetLandObject(stepXSelected, stepYSelected); - - if (p != null) - { - if (!selectedLandObjects.Contains(p)) - { - selectedLandObjects.Add(p); - } - } - } - } - ILandObject masterLandObject = selectedLandObjects[0]; - selectedLandObjects.RemoveAt(0); - - if (selectedLandObjects.Count < 1) - { - return; - } - if (!m_scene.Permissions.CanEditParcel(attempting_user_id, masterLandObject)) - { - return; - } - foreach (ILandObject p in selectedLandObjects) - { - if (p.landData.OwnerID != masterLandObject.landData.OwnerID) - { - return; - } - } - - lock (m_landList) - { - foreach (ILandObject slaveLandObject in selectedLandObjects) - { - m_landList[masterLandObject.landData.LocalID].setLandBitmap( - slaveLandObject.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap())); - performFinalLandJoin(masterLandObject, slaveLandObject); - } - } - SetPrimsTainted(); - - masterLandObject.sendLandUpdateToAvatarsOverMe(); - } - - #endregion - - #region Parcel Updating - - /// - /// Where we send the ParcelOverlay packet to the client - /// - /// The object representing the client - public void SendParcelOverlay(IClientAPI remote_client) - { - const int LAND_BLOCKS_PER_PACKET = 1024; - - byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; - int byteArrayCount = 0; - int sequenceID = 0; - - for (int y = 0; y < 64; y++) - { - for (int x = 0; x < 64; x++) - { - byte tempByte = 0; //This represents the byte for the current 4x4 - - ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); - - if (currentParcelBlock != null) - { - if (currentParcelBlock.landData.OwnerID == remote_client.AgentId) - { - //Owner Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); - } - else if (currentParcelBlock.landData.SalePrice > 0 && - (currentParcelBlock.landData.AuthBuyerID == UUID.Zero || - currentParcelBlock.landData.AuthBuyerID == remote_client.AgentId)) - { - //Sale Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE); - } - else if (currentParcelBlock.landData.OwnerID == UUID.Zero) - { - //Public Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC); - } - else - { - //Other Flag - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER); - } - - //Now for border control - - ILandObject westParcel = null; - ILandObject southParcel = null; - if (x > 0) - { - westParcel = GetLandObject((x - 1) * 4, y * 4); - } - if (y > 0) - { - southParcel = GetLandObject(x * 4, (y - 1) * 4); - } - - if (x == 0) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); - } - else if (westParcel != null && westParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); - } - - if (y == 0) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); - } - else if (southParcel != null && southParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); - } - - byteArray[byteArrayCount] = tempByte; - byteArrayCount++; - if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) - { - remote_client.SendLandParcelOverlay(byteArray, sequenceID); - byteArrayCount = 0; - sequenceID++; - byteArray = new byte[LAND_BLOCKS_PER_PACKET]; - } - } - } - } - } - - public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, - bool snap_selection, IClientAPI remote_client) - { - //Get the land objects within the bounds - List temp = new List(); - int inc_x = end_x - start_x; - int inc_y = end_y - start_y; - for (int x = 0; x < inc_x; x++) - { - for (int y = 0; y < inc_y; y++) - { - ILandObject currentParcel = GetLandObject(start_x + x, start_y + y); - - if (currentParcel != null) - { - if (!temp.Contains(currentParcel)) - { - currentParcel.forceUpdateLandInfo(); - temp.Add(currentParcel); - } - } - } - } - - int requestResult = LandChannel.LAND_RESULT_SINGLE; - if (temp.Count > 1) - { - requestResult = LandChannel.LAND_RESULT_MULTIPLE; - } - - for (int i = 0; i < temp.Count; i++) - { - temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client); - } - - SendParcelOverlay(remote_client); - } - - public void handleParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(localID, out land); - } - - if (land != null) land.updateLandProperties(args, remote_client); - } - - public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) - { - subdivide(west, south, east, north, remote_client.AgentId); - } - - public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) - { - join(west, south, east, north, remote_client.AgentId); - } - - public void handleParcelSelectObjectsRequest(int local_id, int request_type, List returnIDs, IClientAPI remote_client) - { - m_landList[local_id].sendForceObjectSelect(local_id, request_type, returnIDs, remote_client); - } - - public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(local_id, out land); - } - - if (land != null) - { - m_landList[local_id].sendLandObjectOwners(remote_client); - } - else - { - m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id); - } - } - - public void handleParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(local_id, out land); - } - - if (land != null) - { - if (m_scene.Permissions.IsGod(remote_client.AgentId)) - { - land.landData.OwnerID = ownerID; - - m_scene.Broadcast(SendParcelOverlay); - land.sendLandUpdateToClient(remote_client); - } - } - } - - public void handleParcelAbandonRequest(int local_id, IClientAPI remote_client) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(local_id, out land); - } - - if (land != null) - { - if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land)) - { - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; - m_scene.Broadcast(SendParcelOverlay); - land.sendLandUpdateToClient(remote_client); - } - } - } - - public void handleParcelReclaim(int local_id, IClientAPI remote_client) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(local_id, out land); - } - - if (land != null) - { - if (m_scene.Permissions.CanReclaimParcel(remote_client.AgentId, land)) - { - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - land.landData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - else - land.landData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; - land.landData.ClaimDate = Util.UnixTimeSinceEpoch(); - m_scene.Broadcast(SendParcelOverlay); - land.sendLandUpdateToClient(remote_client); - } - } - } - #endregion - - // If the economy has been validated by the economy module, - // and land has been validated as well, this method transfers - // the land ownership - - public void handleLandBuyRequest(Object o, EventManager.LandBuyArgs e) - { - if (e.economyValidated && e.landValidated) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(e.parcelLocalID, out land); - } - - if (land != null) - { - land.updateLandSold(e.agentId, e.groupId, e.groupOwned, (uint)e.transactionID, e.parcelPrice, e.parcelArea); - } - } - } - - // After receiving a land buy packet, first the data needs to - // be validated. This method validates the right to buy the - // parcel - - public void handleLandValidationRequest(Object o, EventManager.LandBuyArgs e) - { - if (e.landValidated == false) - { - ILandObject lob = null; - lock (m_landList) - { - m_landList.TryGetValue(e.parcelLocalID, out lob); - } - - if (lob != null) - { - UUID AuthorizedID = lob.landData.AuthBuyerID; - int saleprice = lob.landData.SalePrice; - UUID pOwnerID = lob.landData.OwnerID; - - bool landforsale = ((lob.landData.Flags & - (uint)(Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects)) != 0); - if ((AuthorizedID == UUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale) - { - // TODO I don't think we have to lock it here, no? - //lock (e) - //{ - e.parcelOwnerID = pOwnerID; - e.landValidated = true; - //} - } - } - } - } - - #region Land Object From Storage Functions - - public void IncomingLandObjectsFromStorage(List data) - { - for (int i = 0; i < data.Count; i++) - { - IncomingLandObjectFromStorage(data[i]); - } - } - - public void IncomingLandObjectFromStorage(LandData data) - { - ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); - new_land.landData = data.Copy(); - new_land.setLandBitmapFromByteArray(); - AddLandObject(new_land); - } - - public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) - { - ILandObject selectedParcel = null; - lock (m_landList) - { - m_landList.TryGetValue(localID, out selectedParcel); - } - - if (selectedParcel == null) return; - - selectedParcel.returnLandObjects(returnType, agentIDs, taskIDs, remoteClient); - } - - public void NoLandDataFromStorage() - { - ResetSimLandObjects(); - } - - #endregion - - public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) - { - lock (m_landList) - { - foreach (LandObject obj in m_landList.Values) - { - obj.setParcelObjectMaxOverride(overrideDel); - } - } - } - - public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) - { - } - - #region CAPS handler - - private void OnRegisterCaps(UUID agentID, Caps caps) - { - string capsBase = "/CAPS/" + caps.CapsObjectPath; - caps.RegisterHandler("RemoteParcelRequest", - new RestStreamHandler("POST", capsBase + remoteParcelRequestPath, - delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return RemoteParcelRequest(request, path, param, agentID, caps); - })); - } - - // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the - // "real" parcelID, because we wouldn't be able to map that to the region the parcel belongs to. - // So, we create a "fake" parcelID by using the regionHandle (64 bit), and the local (integer) x - // and y coordinate (each 8 bit), encoded in a UUID (128 bit). - // - // Request format: - // - // - // location - // - // 1.23 - // 45..6 - // 78.9 - // - // region_id - // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - // - // - private string RemoteParcelRequest(string request, string path, string param, UUID agentID, Caps caps) - { - UUID parcelID = UUID.Zero; - try - { - Hashtable hash = new Hashtable(); - hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); - if (hash.ContainsKey("region_id") && hash.ContainsKey("location")) - { - UUID regionID = (UUID)hash["region_id"]; - ArrayList list = (ArrayList)hash["location"]; - uint x = (uint)(double)list[0]; - uint y = (uint)(double)list[1]; - if (hash.ContainsKey("region_handle")) - { - // if you do a "About Landmark" on a landmark a second time, the viewer sends the - // region_handle it got earlier via RegionHandleRequest - ulong regionHandle = Util.BytesToUInt64Big((byte[])hash["region_handle"]); - parcelID = Util.BuildFakeParcelID(regionHandle, x, y); - } - else if (regionID == m_scene.RegionInfo.RegionID) - { - // a parcel request for a local parcel => no need to query the grid - parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y); - } - else - { - // a parcel request for a parcel in another region. Ask the grid about the region - RegionInfo info = m_scene.CommsManager.GridService.RequestNeighbourInfo(regionID); - if (info != null) - parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y); - } - } - } - catch (LLSD.LLSDParseException e) - { - m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message); - m_log.ErrorFormat("[LAND] ... in request {0}", request); - } - catch(InvalidCastException) - { - m_log.ErrorFormat("[LAND] Wrong type in request {0}", request); - } - - LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); - response.parcel_id = parcelID; - m_log.DebugFormat("[LAND] got parcelID {0}", parcelID); - - return LLSDHelpers.SerialiseLLSDReply(response); - } - - #endregion - - private void handleParcelDwell(int localID, IClientAPI remoteClient) - { - ILandObject selectedParcel = null; - lock (m_landList) - { - if (!m_landList.TryGetValue(localID, out selectedParcel)) - return; - } - - remoteClient.SendParcelDwellReply(localID, selectedParcel.landData.GlobalID, selectedParcel.landData.Dwell); - } - - private void handleParcelInfo(IClientAPI remoteClient, UUID parcelID) - { - if (parcelID == UUID.Zero) - return; - - ExtendedLandData data = (ExtendedLandData)parcelInfoCache.Get(parcelID, delegate(UUID parcel) { - // assume we've got the parcelID we just computed in RemoteParcelRequest - ExtendedLandData extLandData = new ExtendedLandData(); - Util.ParseFakeParcelID(parcel, out extLandData.regionHandle, out extLandData.x, out extLandData.y); - m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}", - extLandData.regionHandle, extLandData.x, extLandData.y); - - // for this region or for somewhere else? - if (extLandData.regionHandle == m_scene.RegionInfo.RegionHandle) - { - extLandData.landData = this.GetLandObject(extLandData.x, extLandData.y).landData; - } - else - { - extLandData.landData = m_scene.CommsManager.GridService.RequestLandData(extLandData.regionHandle, - extLandData.x, - extLandData.y); - if (extLandData.landData == null) - { - // we didn't find the region/land => don't cache - return null; - } - } - return extLandData; - }); - - if (data != null) // if we found some data, send it - { - RegionInfo info; - if (data.regionHandle == m_scene.RegionInfo.RegionHandle) - { - info = m_scene.RegionInfo; - } - else - { - // most likely still cached from building the extLandData entry - info = m_scene.CommsManager.GridService.RequestNeighbourInfo(data.regionHandle); - } - // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. - m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...", - data.landData.Name, data.regionHandle); - remoteClient.SendParcelInfo(info, data.landData, parcelID, data.x, data.y); - } - else - m_log.Debug("[LAND] got no parcelinfo; not sending"); - } - - public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) - { - ILandObject land; - lock (m_landList) - { - m_landList.TryGetValue(localID, out land); - } - - if (land == null) return; - - if (!m_scene.Permissions.CanEditParcel(remoteClient.AgentId, land)) - return; - - land.landData.OtherCleanTime = otherCleanTime; - - UpdateLandObject(localID, land.landData); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs b/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs deleted file mode 100644 index b5f7225..0000000 --- a/OpenSim/Region/Environment/Modules/World/Land/LandObject.cs +++ /dev/null @@ -1,930 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Land -{ - /// - /// Keeps track of a specific piece of land's information - /// - public class LandObject : ILandObject - { - #region Member Variables - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private bool[,] m_landBitmap = new bool[64,64]; - - protected LandData m_landData = new LandData(); - protected Scene m_scene; - protected List primsOverMe = new List(); - - public bool[,] landBitmap - { - get { return m_landBitmap; } - set { m_landBitmap = value; } - } - - #endregion - - #region ILandObject Members - - public LandData landData - { - get { return m_landData; } - - set { m_landData = value; } - } - - public UUID regionUUID - { - get { return m_scene.RegionInfo.RegionID; } - } - - #region Constructors - - public LandObject(UUID owner_id, bool is_group_owned, Scene scene) - { - m_scene = scene; - landData.OwnerID = owner_id; - landData.IsGroupOwned = is_group_owned; - } - - #endregion - - #region Member Functions - - #region General Functions - - /// - /// Checks to see if this land object contains a point - /// - /// - /// - /// Returns true if the piece of land contains the specified point - public bool containsPoint(int x, int y) - { - if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize) - { - return (landBitmap[x / 4, y / 4] == true); - } - else - { - return false; - } - } - - public ILandObject Copy() - { - ILandObject newLand = new LandObject(landData.OwnerID, landData.IsGroupOwned, m_scene); - - //Place all new variables here! - newLand.landBitmap = (bool[,]) (landBitmap.Clone()); - newLand.landData = landData.Copy(); - - return newLand; - } - - - static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount; - static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount; - - public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) - { - overrideParcelMaxPrimCount = overrideDel; - } - public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) - { - overrideSimulatorMaxPrimCount = overrideDel; - } - - public int getParcelMaxPrimCount(ILandObject thisObject) - { - if (overrideParcelMaxPrimCount != null) - { - return overrideParcelMaxPrimCount(thisObject); - } - else - { - //Normal Calculations - return Convert.ToInt32( - Math.Round((Convert.ToDecimal(landData.Area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity * - Convert.ToDecimal(m_scene.RegionInfo.RegionSettings.ObjectBonus))); ; - } - } - public int getSimulatorMaxPrimCount(ILandObject thisObject) - { - if (overrideSimulatorMaxPrimCount != null) - { - return overrideSimulatorMaxPrimCount(thisObject); - } - else - { - //Normal Calculations - return m_scene.objectCapacity; - } - } - #endregion - - #region Packet Request Handling - - public void sendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) - { - IEstateModule estateModule = m_scene.RequestModuleInterface(); - uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); - if (estateModule != null) - regionFlags = estateModule.GetRegionFlags(); - - // In a perfect world, this would have worked. - // -// if ((landData.Flags & (uint)Parcel.ParcelFlags.AllowLandmark) != 0) -// regionFlags |= (uint)RegionFlags.AllowLandmark; -// if (landData.OwnerID == remote_client.AgentId) -// regionFlags |= (uint)RegionFlags.AllowSetHome; - remote_client.SendLandProperties(sequence_id, - snap_selection, request_result, landData, - (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, - getParcelMaxPrimCount(this), - getSimulatorMaxPrimCount(this), regionFlags); - } - - public void updateLandProperties(LandUpdateArgs args, IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this)) - { - //Needs later group support - LandData newData = landData.Copy(); - - if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice) - { - if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this)) - { - newData.AuthBuyerID = args.AuthBuyerID; - newData.SalePrice = args.SalePrice; - } - } - newData.Category = args.Category; - newData.Description = args.Desc; - newData.GroupID = args.GroupID; - newData.LandingType = args.LandingType; - newData.MediaAutoScale = args.MediaAutoScale; - newData.MediaID = args.MediaID; - newData.MediaURL = args.MediaURL; - newData.MusicURL = args.MusicURL; - newData.Name = args.Name; - newData.Flags = args.ParcelFlags; - newData.PassHours = args.PassHours; - newData.PassPrice = args.PassPrice; - newData.SnapshotID = args.SnapshotID; - newData.UserLocation = args.UserLocation; - newData.UserLookAt = args.UserLookAt; - - m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData); - - sendLandUpdateToAvatarsOverMe(); - } - } - - public void updateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) - { - LandData newData = landData.Copy(); - newData.OwnerID = avatarID; - newData.GroupID = groupID; - newData.IsGroupOwned = groupOwned; - //newData.auctionID = AuctionID; - newData.ClaimDate = Util.UnixTimeSinceEpoch(); - newData.ClaimPrice = claimprice; - newData.SalePrice = 0; - newData.AuthBuyerID = UUID.Zero; - newData.Flags &= ~(uint) (Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects); - m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData); - - sendLandUpdateToAvatarsOverMe(); - } - - public bool isEitherBannedOrRestricted(UUID avatar) - { - if (isBannedFromLand(avatar)) - { - return true; - } - else if (isRestrictedFromLand(avatar)) - { - return true; - } - return false; - } - - public bool isBannedFromLand(UUID avatar) - { - if ((landData.Flags & (uint) Parcel.ParcelFlags.UseBanList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = AccessList.Ban; - entry.Time = new DateTime(); - if (landData.ParcelAccessList.Contains(entry)) - { - //They are banned, so lets send them a notice about this parcel - return true; - } - } - return false; - } - - public bool isRestrictedFromLand(UUID avatar) - { - if ((landData.Flags & (uint) Parcel.ParcelFlags.UseAccessList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = AccessList.Access; - entry.Time = new DateTime(); - if (!landData.ParcelAccessList.Contains(entry)) - { - //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel - return true; - } - } - return false; - } - - public void sendLandUpdateToClient(IClientAPI remote_client) - { - sendLandProperties(0, false, 0, remote_client); - } - - public void sendLandUpdateToAvatarsOverMe() - { - List avatars = m_scene.GetAvatars(); - ILandObject over = null; - for (int i = 0; i < avatars.Count; i++) - { - try - { - over = - m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatars[i].AbsolutePosition.X), 0, 255), - Util.Clamp((int)Math.Round(avatars[i].AbsolutePosition.Y), 0, 255)); - } - catch (Exception) - { - m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatars[i].AbsolutePosition.X) + " y: " + - Math.Round(avatars[i].AbsolutePosition.Y)); - } - - if (over != null) - { - if (over.landData.LocalID == landData.LocalID) - { - if (((over.landData.Flags & (uint)Parcel.ParcelFlags.AllowDamage) != 0) && m_scene.RegionInfo.RegionSettings.AllowDamage) - avatars[i].Invulnerable = false; - else - avatars[i].Invulnerable = true; - - sendLandUpdateToClient(avatars[i].ControllingClient); - } - } - } - } - - #endregion - - #region AccessList Functions - - public List createAccessListArrayByFlag(AccessList flag) - { - List list = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in landData.ParcelAccessList) - { - if (entry.Flags == flag) - { - list.Add(entry.AgentID); - } - } - if (list.Count == 0) - { - list.Add(UUID.Zero); - } - - return list; - } - - public void sendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, - IClientAPI remote_client) - { - - if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) - { - List avatars = createAccessListArrayByFlag(AccessList.Access); - remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,landData.LocalID); - } - - if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) - { - List avatars = createAccessListArrayByFlag(AccessList.Ban); - remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, landData.LocalID); - } - } - - public void updateAccessList(uint flags, List entries, IClientAPI remote_client) - { - LandData newData = landData.Copy(); - - if (entries.Count == 1 && entries[0].AgentID == UUID.Zero) - { - entries.Clear(); - } - - List toRemove = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList) - { - if (entry.Flags == (AccessList)flags) - { - toRemove.Add(entry); - } - } - - foreach (ParcelManager.ParcelAccessEntry entry in toRemove) - { - newData.ParcelAccessList.Remove(entry); - } - foreach (ParcelManager.ParcelAccessEntry entry in entries) - { - ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); - temp.AgentID = entry.AgentID; - temp.Time = new DateTime(); //Pointless? Yes. - temp.Flags = (AccessList)flags; - - if (!newData.ParcelAccessList.Contains(temp)) - { - newData.ParcelAccessList.Add(temp); - } - } - - m_scene.LandChannel.UpdateLandObject(landData.LocalID, newData); - } - - #endregion - - #region Update Functions - - public void updateLandBitmapByteArray() - { - landData.Bitmap = convertLandBitmapToBytes(); - } - - /// - /// Update all settings in land such as area, bitmap byte array, etc - /// - public void forceUpdateLandInfo() - { - updateAABBAndAreaValues(); - updateLandBitmapByteArray(); - } - - public void setLandBitmapFromByteArray() - { - landBitmap = convertBytesToLandBitmap(); - } - - /// - /// Updates the AABBMin and AABBMax values after area/shape modification of the land object - /// - private void updateAABBAndAreaValues() - { - int min_x = 64; - int min_y = 64; - int max_x = 0; - int max_y = 0; - int tempArea = 0; - int x, y; - for (x = 0; x < 64; x++) - { - for (y = 0; y < 64; y++) - { - if (landBitmap[x, y] == true) - { - if (min_x > x) min_x = x; - if (min_y > y) min_y = y; - if (max_x < x) max_x = x; - if (max_y < y) max_y = y; - tempArea += 16; //16sqm peice of land - } - } - } - int tx = min_x * 4; - if (tx > 255) - tx = 255; - int ty = min_y * 4; - if (ty > 255) - ty = 255; - landData.AABBMin = - new Vector3((float) (min_x * 4), (float) (min_y * 4), - (float) m_scene.Heightmap[tx, ty]); - - tx = max_x * 4; - if (tx > 255) - tx = 255; - ty = max_y * 4; - if (ty > 255) - ty = 255; - landData.AABBMax = - new Vector3((float) (max_x * 4), (float) (max_y * 4), - (float) m_scene.Heightmap[tx, ty]); - landData.Area = tempArea; - } - - #endregion - - #region Land Bitmap Functions - - /// - /// Sets the land's bitmap manually - /// - /// 64x64 block representing where this land is on a map - public void setLandBitmap(bool[,] bitmap) - { - if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap"); - } - else - { - //Valid: Lets set it - landBitmap = bitmap; - forceUpdateLandInfo(); - } - } - - /// - /// Gets the land's bitmap manually - /// - /// - public bool[,] getLandBitmap() - { - return landBitmap; - } - - /// - /// Full sim land object creation - /// - /// - public bool[,] basicFullRegionLandBitmap() - { - return getSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); - } - - /// - /// Used to modify the bitmap between the x and y points. Points use 64 scale - /// - /// - /// - /// - /// - /// - public bool[,] getSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) - { - bool[,] tempBitmap = new bool[64,64]; - tempBitmap.Initialize(); - - tempBitmap = modifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); - return tempBitmap; - } - - /// - /// Change a land bitmap at within a square and set those points to a specific value - /// - /// - /// - /// - /// - /// - /// - /// - public bool[,] modifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, - bool set_value) - { - if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); - } - - int x, y; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - if (x >= start_x / 4 && x < end_x / 4 - && y >= start_y / 4 && y < end_y / 4) - { - land_bitmap[x, y] = set_value; - } - } - } - return land_bitmap; - } - - /// - /// Join the true values of 2 bitmaps together - /// - /// - /// - /// - public bool[,] mergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) - { - if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); - } - if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); - } - - int x, y; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - if (bitmap_add[x, y]) - { - bitmap_base[x, y] = true; - } - } - } - return bitmap_base; - } - - /// - /// Converts the land bitmap to a packet friendly byte array - /// - /// - private byte[] convertLandBitmapToBytes() - { - byte[] tempConvertArr = new byte[512]; - byte tempByte = 0; - int x, y, i, byteNum = 0; - i = 0; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - tempByte = Convert.ToByte(tempByte | Convert.ToByte(landBitmap[x, y]) << (i++ % 8)); - if (i % 8 == 0) - { - tempConvertArr[byteNum] = tempByte; - tempByte = (byte) 0; - i = 0; - byteNum++; - } - } - } - return tempConvertArr; - } - - private bool[,] convertBytesToLandBitmap() - { - bool[,] tempConvertMap = new bool[64,64]; - tempConvertMap.Initialize(); - byte tempByte = 0; - int x = 0, y = 0, i = 0, bitNum = 0; - for (i = 0; i < 512; i++) - { - tempByte = landData.Bitmap[i]; - for (bitNum = 0; bitNum < 8; bitNum++) - { - bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); - tempConvertMap[x, y] = bit; - x++; - if (x > 63) - { - x = 0; - y++; - } - } - } - return tempConvertMap; - } - - #endregion - - #region Object Select and Object Owner Listing - - public void sendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) - { - List resultLocalIDs = new List(); - try - { - lock (primsOverMe) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.LocalId > 0) - { - if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == landData.OwnerID) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == landData.GroupID && landData.GroupID != UUID.Zero) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER && - obj.OwnerID != remote_client.AgentId) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID)) - { - resultLocalIDs.Add(obj.LocalId); - } - } - } - } - } catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to force select the parcel objects. Arr."); - } - - remote_client.SendForceClientSelectObjects(resultLocalIDs); - } - } - - /// - /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes - /// aggreagete details such as the number of prims. - /// - /// - /// - /// A - /// - public void sendLandObjectOwners(IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) - { - Dictionary primCount = new Dictionary(); - - lock (primsOverMe) - { - try - { - - foreach (SceneObjectGroup obj in primsOverMe) - { - try - { - if (!primCount.ContainsKey(obj.OwnerID)) - { - primCount.Add(obj.OwnerID, 0); - } - } - catch (NullReferenceException) - { - m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel"); - } - try - { - primCount[obj.OwnerID] += obj.PrimCount; - } - catch (KeyNotFoundException) - { - m_log.Error("[LAND]: Unable to match a prim with it's owner."); - } - } - } - catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to Enumerate Land object arr."); - } - } - - remote_client.SendLandObjectOwners(primCount); - } - } - - public Dictionary getLandObjectOwners() - { - Dictionary ownersAndCount = new Dictionary(); - lock (primsOverMe) - { - try - { - - foreach (SceneObjectGroup obj in primsOverMe) - { - if (!ownersAndCount.ContainsKey(obj.OwnerID)) - { - ownersAndCount.Add(obj.OwnerID, 0); - } - ownersAndCount[obj.OwnerID] += obj.PrimCount; - } - } - catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to enumerate land owners. arr."); - } - - } - return ownersAndCount; - } - - #endregion - - #region Object Returning - - public void returnObject(SceneObjectGroup obj) - { - SceneObjectGroup[] objs = new SceneObjectGroup[1]; - objs[0] = obj; - m_scene.returnObjects(objs, obj.OwnerID); - } - - public void returnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) - { - Dictionary> returns = - new Dictionary>(); - - lock (primsOverMe) - { - if (type == (uint)ObjectReturnType.Owner) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.OwnerID == m_landData.OwnerID) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.GroupID == m_landData.GroupID) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.Other) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.OwnerID != m_landData.OwnerID && - (obj.GroupID != m_landData.GroupID || - m_landData.GroupID == UUID.Zero)) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.List) - { - List ownerlist = new List(owners); - - foreach (SceneObjectGroup obj in primsOverMe) - { - if (ownerlist.Contains(obj.OwnerID)) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - } - - foreach (List ol in returns.Values) - m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); - } - - #endregion - - #region Object Adding/Removing from Parcel - - public void resetLandPrimCounts() - { - landData.GroupPrims = 0; - landData.OwnerPrims = 0; - landData.OtherPrims = 0; - landData.SelectedPrims = 0; - - - lock (primsOverMe) - primsOverMe.Clear(); - } - - public void addPrimToCount(SceneObjectGroup obj) - { - - UUID prim_owner = obj.OwnerID; - int prim_count = obj.PrimCount; - - if (obj.IsSelected) - { - landData.SelectedPrims += prim_count; - } - else - { - if (prim_owner == landData.OwnerID) - { - landData.OwnerPrims += prim_count; - } - else if ((obj.GroupID == landData.GroupID || - prim_owner == landData.GroupID) && - landData.GroupID != UUID.Zero) - { - landData.GroupPrims += prim_count; - } - else - { - landData.OtherPrims += prim_count; - } - } - - lock (primsOverMe) - primsOverMe.Add(obj); - } - - public void removePrimFromCount(SceneObjectGroup obj) - { - lock (primsOverMe) - { - if (primsOverMe.Contains(obj)) - { - UUID prim_owner = obj.OwnerID; - int prim_count = obj.PrimCount; - - if (prim_owner == landData.OwnerID) - { - landData.OwnerPrims -= prim_count; - } - else if (obj.GroupID == landData.GroupID || - prim_owner == landData.GroupID) - { - landData.GroupPrims -= prim_count; - } - else - { - landData.OtherPrims -= prim_count; - } - - primsOverMe.Remove(obj); - } - } - } - - #endregion - - #endregion - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs deleted file mode 100644 index 9165554..0000000 --- a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.NPC -{ - public class NPCAvatar : IClientAPI - { - private readonly string m_firstname; - private readonly string m_lastname; - private readonly Vector3 m_startPos; - private readonly UUID m_uuid = UUID.Random(); - private readonly Scene m_scene; - - - public NPCAvatar(string firstname, string lastname, Vector3 position, Scene scene) - { - m_firstname = firstname; - m_lastname = lastname; - m_startPos = position; - m_scene = scene; - } - - public IScene Scene - { - get { return m_scene; } - } - - public void Say(string message) - { - SendOnChatFromClient(message, ChatTypeEnum.Say); - } - - public void Shout(string message) - { - SendOnChatFromClient(message, ChatTypeEnum.Shout); - } - - public void Whisper(string message) - { - SendOnChatFromClient(message, ChatTypeEnum.Whisper); - } - - public void Broadcast(string message) - { - SendOnChatFromClient(message, ChatTypeEnum.Broadcast); - } - - public void GiveMoney(UUID target, int amount) - { - OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment"); - } - - public void InstantMessage(UUID target, string message) - { - OnInstantMessage(this, new GridInstantMessage(m_scene, - m_uuid, m_firstname + " " + m_lastname, - target, 0, false, message, - UUID.Zero, false, Position, new byte[0])); - } - - public void SendAgentOffline(UUID[] agentIDs) - { - - } - - public void SendAgentOnline(UUID[] agentIDs) - { - - } - public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, - Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) - { - - } - - public void SendAdminResponse(UUID Token, uint AdminLevel) - { - - } - - public void SendGroupMembership(GroupMembershipData[] GroupMembership) - { - - } - - public UUID GetDefaultAnimation(string name) - { - return UUID.Zero; - } - - public Vector3 Position - { - get { return m_scene.Entities[m_uuid].AbsolutePosition; } - set { m_scene.Entities[m_uuid].AbsolutePosition = value; } - } - - public bool SendLogoutPacketWhenClosing - { - set { } - } - - #region Internal Functions - - private void SendOnChatFromClient(string message, ChatTypeEnum chatType) - { - OSChatMessage chatFromClient = new OSChatMessage(); - chatFromClient.Channel = 0; - chatFromClient.From = Name; - chatFromClient.Message = message; - chatFromClient.Position = StartPos; - chatFromClient.Scene = m_scene; - chatFromClient.Sender = this; - chatFromClient.SenderUUID = AgentId; - chatFromClient.Type = chatType; - - OnChatFromClient(this, chatFromClient); - } - - #endregion - - #region Event Definitions IGNORE - -// disable warning: public events constituting public API -#pragma warning disable 67 - public event Action OnLogout; - public event ObjectPermissions OnObjectPermissions; - - public event MoneyTransferRequest OnMoneyTransferRequest; - public event ParcelBuy OnParcelBuy; - public event Action OnConnectionClosed; - public event GenericMessage OnGenericMessage; - public event ImprovedInstantMessage OnInstantMessage; - public event ChatMessage OnChatFromClient; - public event TextureRequest OnRequestTexture; - public event RezObject OnRezObject; - public event ModifyTerrain OnModifyTerrain; - public event SetAppearance OnSetAppearance; - public event AvatarNowWearing OnAvatarNowWearing; - public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; - public event UUIDNameRequest OnDetachAttachmentIntoInv; - public event ObjectAttach OnObjectAttach; - public event ObjectDeselect OnObjectDetach; - public event ObjectDrop OnObjectDrop; - public event StartAnim OnStartAnim; - public event StopAnim OnStopAnim; - public event LinkObjects OnLinkObjects; - public event DelinkObjects OnDelinkObjects; - public event RequestMapBlocks OnRequestMapBlocks; - public event RequestMapName OnMapNameRequest; - public event TeleportLocationRequest OnTeleportLocationRequest; - public event TeleportLandmarkRequest OnTeleportLandmarkRequest; - public event DisconnectUser OnDisconnectUser; - public event RequestAvatarProperties OnRequestAvatarProperties; - public event SetAlwaysRun OnSetAlwaysRun; - - public event DeRezObject OnDeRezObject; - public event Action OnRegionHandShakeReply; - public event GenericCall2 OnRequestWearables; - public event GenericCall2 OnCompleteMovementToRegion; - public event UpdateAgent OnAgentUpdate; - public event AgentRequestSit OnAgentRequestSit; - public event AgentSit OnAgentSit; - public event AvatarPickerRequest OnAvatarPickerRequest; - public event Action OnRequestAvatarsData; - public event AddNewPrim OnAddPrim; - public event RequestGodlikePowers OnRequestGodlikePowers; - public event GodKickUser OnGodKickUser; - public event ObjectDuplicate OnObjectDuplicate; - public event GrabObject OnGrabObject; - public event ObjectSelect OnDeGrabObject; - public event MoveObject OnGrabUpdate; - public event ViewerEffectEventHandler OnViewerEffect; - - public event FetchInventory OnAgentDataUpdateRequest; - public event TeleportLocationRequest OnSetStartLocationRequest; - - public event UpdateShape OnUpdatePrimShape; - public event ObjectExtraParams OnUpdateExtraParams; - public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; - public event ObjectSelect OnObjectSelect; - public event GenericCall7 OnObjectDescription; - public event GenericCall7 OnObjectName; - public event GenericCall7 OnObjectClickAction; - public event GenericCall7 OnObjectMaterial; - public event UpdatePrimFlags OnUpdatePrimFlags; - public event UpdatePrimTexture OnUpdatePrimTexture; - public event UpdateVector OnUpdatePrimGroupPosition; - public event UpdateVector OnUpdatePrimSinglePosition; - public event UpdatePrimRotation OnUpdatePrimGroupRotation; - public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; - public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; - public event UpdateVector OnUpdatePrimScale; - public event UpdateVector OnUpdatePrimGroupScale; - public event StatusChange OnChildAgentStatus; - public event GenericCall2 OnStopMovement; - public event Action OnRemoveAvatar; - - public event CreateNewInventoryItem OnCreateNewInventoryItem; - public event CreateInventoryFolder OnCreateNewInventoryFolder; - public event UpdateInventoryFolder OnUpdateInventoryFolder; - public event MoveInventoryFolder OnMoveInventoryFolder; - public event RemoveInventoryFolder OnRemoveInventoryFolder; - public event RemoveInventoryItem OnRemoveInventoryItem; - public event FetchInventoryDescendents OnFetchInventoryDescendents; - public event PurgeInventoryDescendents OnPurgeInventoryDescendents; - public event FetchInventory OnFetchInventory; - public event RequestTaskInventory OnRequestTaskInventory; - public event UpdateInventoryItem OnUpdateInventoryItem; - public event CopyInventoryItem OnCopyInventoryItem; - public event MoveInventoryItem OnMoveInventoryItem; - public event UDPAssetUploadRequest OnAssetUploadRequest; - public event XferReceive OnXferReceive; - public event RequestXfer OnRequestXfer; - public event AbortXfer OnAbortXfer; - public event ConfirmXfer OnConfirmXfer; - public event RezScript OnRezScript; - public event UpdateTaskInventory OnUpdateTaskInventory; - public event MoveTaskInventory OnMoveTaskItem; - public event RemoveTaskInventory OnRemoveTaskItem; - public event RequestAsset OnRequestAsset; - - public event UUIDNameRequest OnNameFromUUIDRequest; - public event UUIDNameRequest OnUUIDGroupNameRequest; - - public event ParcelPropertiesRequest OnParcelPropertiesRequest; - public event ParcelDivideRequest OnParcelDivideRequest; - public event ParcelJoinRequest OnParcelJoinRequest; - public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; - public event ParcelAbandonRequest OnParcelAbandonRequest; - public event ParcelGodForceOwner OnParcelGodForceOwner; - public event ParcelReclaim OnParcelReclaim; - public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest; - public event ParcelAccessListRequest OnParcelAccessListRequest; - public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; - public event ParcelSelectObjects OnParcelSelectObjects; - public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; - public event ObjectDeselect OnObjectDeselect; - public event RegionInfoRequest OnRegionInfoRequest; - public event EstateCovenantRequest OnEstateCovenantRequest; - public event RequestTerrain OnRequestTerrain; - public event RequestTerrain OnUploadTerrain; - public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; - - public event FriendActionDelegate OnApproveFriendRequest; - public event FriendActionDelegate OnDenyFriendRequest; - public event FriendshipTermination OnTerminateFriendship; - - public event EconomyDataRequest OnEconomyDataRequest; - public event MoneyBalanceRequest OnMoneyBalanceRequest; - public event UpdateAvatarProperties OnUpdateAvatarProperties; - - public event ObjectIncludeInSearch OnObjectIncludeInSearch; - public event UUIDNameRequest OnTeleportHomeRequest; - - public event ScriptAnswer OnScriptAnswer; - public event RequestPayPrice OnRequestPayPrice; - public event ObjectSaleInfo OnObjectSaleInfo; - public event ObjectBuy OnObjectBuy; - public event BuyObjectInventory OnBuyObjectInventory; - public event AgentSit OnUndo; - - public event ForceReleaseControls OnForceReleaseControls; - public event GodLandStatRequest OnLandStatRequest; - public event RequestObjectPropertiesFamily OnObjectGroupRequest; - - public event DetailedEstateDataRequest OnDetailedEstateDataRequest; - public event SetEstateFlagsRequest OnSetEstateFlagsRequest; - public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; - public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; - public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; - public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; - public event SetRegionTerrainSettings OnSetRegionTerrainSettings; - public event BakeTerrain OnBakeTerrain; - public event EstateRestartSimRequest OnEstateRestartSimRequest; - public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; - public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; - public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest; - public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest; - public event EstateDebugRegionRequest OnEstateDebugRegionRequest; - public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; - public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; - public event EstateChangeInfo OnEstateChangeInfo; - public event ScriptReset OnScriptReset; - public event GetScriptRunning OnGetScriptRunning; - public event SetScriptRunning OnSetScriptRunning; - public event UpdateVector OnAutoPilotGo; - - public event TerrainUnacked OnUnackedTerrain; - - public event RegionHandleRequest OnRegionHandleRequest; - public event ParcelInfoRequest OnParcelInfoRequest; - - public event ActivateGesture OnActivateGesture; - public event DeactivateGesture OnDeactivateGesture; - public event ObjectOwner OnObjectOwner; - - public event DirPlacesQuery OnDirPlacesQuery; - public event DirFindQuery OnDirFindQuery; - public event DirLandQuery OnDirLandQuery; - public event DirPopularQuery OnDirPopularQuery; - public event DirClassifiedQuery OnDirClassifiedQuery; - public event EventInfoRequest OnEventInfoRequest; - public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; - - public event MapItemRequest OnMapItemRequest; - - public event OfferCallingCard OnOfferCallingCard; - public event AcceptCallingCard OnAcceptCallingCard; - public event DeclineCallingCard OnDeclineCallingCard; - public event SoundTrigger OnSoundTrigger; - - public event StartLure OnStartLure; - public event TeleportLureRequest OnTeleportLureRequest; - public event NetworkStats OnNetworkStatsUpdate; - - public event ClassifiedInfoRequest OnClassifiedInfoRequest; - public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; - public event ClassifiedDelete OnClassifiedDelete; - public event ClassifiedDelete OnClassifiedGodDelete; - - public event EventNotificationAddRequest OnEventNotificationAddRequest; - public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; - public event EventGodDelete OnEventGodDelete; - - public event ParcelDwellRequest OnParcelDwellRequest; - - public event UserInfoRequest OnUserInfoRequest; - public event UpdateUserInfo OnUpdateUserInfo; - -#pragma warning restore 67 - - #endregion - - public void ActivateGesture(UUID assetId, UUID gestureId) - { - } - public void DeactivateGesture(UUID assetId, UUID gestureId) - { - } - - #region Overrriden Methods IGNORE - - public virtual Vector3 StartPos - { - get { return m_startPos; } - set { } - } - - public virtual UUID AgentId - { - get { return m_uuid; } - } - - public UUID SessionId - { - get { return UUID.Zero; } - } - - public UUID SecureSessionId - { - get { return UUID.Zero; } - } - - public virtual string FirstName - { - get { return m_firstname; } - } - - public virtual string LastName - { - get { return m_lastname; } - } - - public virtual String Name - { - get { return FirstName + " " + LastName; } - } - - public bool IsActive - { - get { return true; } - set { } - } - - public UUID ActiveGroupId - { - get { return UUID.Zero; } - } - - public string ActiveGroupName - { - get { return String.Empty; } - } - - public ulong ActiveGroupPowers - { - get { return 0; } - } - - public bool IsGroupMember(UUID groupID) - { - return false; - } - - public ulong GetGroupPowers(UUID groupID) - { - return 0; - } - - public virtual int NextAnimationSequenceNumber - { - get { return 1; } - } - - public virtual void SendWearables(AvatarWearable[] wearables, int serial) - { - } - - public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) - { - } - - public virtual void Kick(string message) - { - } - - public virtual void SendStartPingCheck(byte seq) - { - } - - public virtual void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List Data) - { - } - - public virtual void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle) - { - - } - - public virtual void SendKillObject(ulong regionHandle, uint localID) - { - } - - public virtual void SetChildAgentThrottle(byte[] throttle) - { - } - public byte[] GetThrottlesPacked(float multiplier) - { - return new byte[0]; - } - - - public virtual void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId) - { - } - - public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) - { - } - - public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, byte source, byte audible) - { - } - - public void SendInstantMessage(UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, uint timeStamp) - { - - } - - public void SendInstantMessage(UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, uint timeStamp, UUID transationID, bool fromGroup, byte[] binaryBucket) - { - - } - - public void SendGenericMessage(string method, List message) - { - - } - - public virtual void SendLayerData(float[] map) - { - } - - public virtual void SendLayerData(int px, int py, float[] map) - { - } - public virtual void SendLayerData(int px, int py, float[] map, bool track) - { - } - - public virtual void SendWindData(Vector2[] windSpeeds) { } - - public virtual void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) - { - } - - public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint) - { - } - - public virtual AgentCircuitData RequestClientInfo() - { - return new AgentCircuitData(); - } - - public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, - IPEndPoint newRegionExternalEndPoint, string capsURL) - { - } - - public virtual void SendMapBlock(List mapBlocks, uint flag) - { - } - - public virtual void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags) - { - } - - public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, - uint locationID, uint flags, string capsURL) - { - } - - public virtual void SendTeleportFailed(string reason) - { - } - - public virtual void SendTeleportLocationStart() - { - } - - public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) - { - } - - public virtual void SendPayPrice(UUID objectID, int[] payPrice) - { - } - - public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, - uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) - { - } - - public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, - Vector3 position, Vector3 velocity, Quaternion rotation) - { - } - - public virtual void SendCoarseLocationUpdate(List CoarseLocations) - { - } - - public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - } - - public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string msg, UUID textureID, int ch, string[] buttonlabels) - { - } - - public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, - PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, - Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, - UUID objectID, UUID ownerID, string text, byte[] color, - uint parentID, - byte[] particleSystem, byte clickAction, byte material) - { - } - public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, - PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, - Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, - UUID objectID, UUID ownerID, string text, byte[] color, - uint parentID, - byte[] particleSystem, byte clickAction, byte material, byte[] textureanimation, - bool attachment, uint AttachmentPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius) - { - } - public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, - Vector3 position, Quaternion rotation, Vector3 velocity, - Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) - { - } - - public virtual void SendInventoryFolderDetails(UUID ownerID, UUID folderID, - List items, - List folders, - bool fetchFolders, - bool fetchItems) - { - } - - public virtual void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) - { - } - - public virtual void SendInventoryItemCreateUpdate(InventoryItemBase Item) - { - } - - public virtual void SendRemoveInventoryItem(UUID itemID) - { - } - - /// IClientAPI.SendBulkUpdateInventory(InventoryItemBase) - public virtual void SendBulkUpdateInventory(InventoryItemBase item) - { - } - - public virtual void SendBulkUpdateInventory(InventoryFolderBase folderBase) - {} - - public void SendTakeControls(int controls, bool passToAgent, bool TakeControls) - { - } - - public virtual void SendTaskInventory(UUID taskID, short serial, byte[] fileName) - { - } - - public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data) - { - } - - public virtual void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, - int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, - int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, - int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) - { - - } - public virtual void SendNameReply(UUID profileId, string firstname, string lastname) - { - } - - public virtual void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID) - { - } - - public virtual void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain, - byte flags) - { - } - - public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) - { - } - - public void SendAttachedSoundGainChange(UUID objectID, float gain) - { - - } - - public void SendAlertMessage(string message) - { - } - - public void SendAgentAlertMessage(string message, bool modal) - { - } - - public void SendSystemAlertMessage(string message) - { - } - - public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, - string url) - { - } - - public virtual void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) - { - if (OnRegionHandShakeReply != null) - { - OnRegionHandShakeReply(this); - } - - if (OnCompleteMovementToRegion != null) - { - OnCompleteMovementToRegion(); - } - } - public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) - { - } - - public void SendConfirmXfer(ulong xferID, uint PacketID) - { - } - - public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) - { - } - - public void SendInitiateDownload(string simFileName, string clientFileName) - { - } - - public void SendImageFirstPart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) - { - } - - public void SendImageNotFound(UUID imageid) - { - } - - public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) - { - } - - public void SendShutdownConnectionNotice() - { - } - - public void SendSimStats(SimStats stats) - { - } - - public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, - uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, - uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, - UUID LastOwnerID, string ObjectName, string Description) - { - } - - public void SendObjectPropertiesReply(UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, - UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, - UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, - string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, - uint BaseMask, byte saleType, int salePrice) - { - } - - public bool AddMoney(int debit) - { - return false; - } - - public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase) - { - } - - public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks) - { - } - - public void SendViewerTime(int phase) - { - } - - public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, - string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL, - UUID partnerID) - { - } - - public void SendAsset(AssetRequestToClient req) - { - } - - public void SendTexture(AssetBase TextureAsset) - { - } - - public void SetDebugPacketLevel(int newDebug) - { - } - - public void InPacket(object NewPack) - { - } - - public void ProcessInPacket(Packet NewPack) - { - } - - public void Close(bool ShutdownCircuit) - { - } - - public void Start() - { - } - - public void Stop() - { - } - - private uint m_circuitCode; - - public uint CircuitCode - { - get { return m_circuitCode; } - set { m_circuitCode = value; } - } - - public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) - { - - } - public void SendLogoutPacket() - { - } - - public void Terminate() - { - } - - public ClientInfo GetClientInfo() - { - return null; - } - - public void SetClientInfo(ClientInfo info) - { - } - - public void SendScriptQuestion(UUID objectID, string taskName, string ownerName, UUID itemID, int question) - { - } - public void SendHealth(float health) - { - } - - public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) - { - } - - public void SendBannedUserList(UUID invoice, EstateBan[] banlist, uint estateID) - { - } - - public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) - { - } - public void SendEstateCovenantInformation(UUID covenant) - { - } - public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) - { - } - - public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor,int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) - { - } - public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) - { - } - public void SendForceClientSelectObjects(List objectIDs) - { - } - public void SendLandObjectOwners(Dictionary ownersAndCount) - { - } - public void SendLandParcelOverlay(byte[] data, int sequence_id) - { - } - - public void SendGroupNameReply(UUID groupLLUID, string GroupName) - { - } - - public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) - { - } - - public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) - { - } - #endregion - - - public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) - { - } - - public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, - byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, - byte mediaLoop) - { - } - - public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) - { - } - - public void SendClearFollowCamProperties (UUID objectID) - { - } - - public void SendRegionHandle (UUID regoinID, ulong handle) - { - } - - public void SendParcelInfo (RegionInfo info, LandData land, UUID parcelID, uint x, uint y) - { - } - - public void SetClientOption(string option, string value) - { - } - - public string GetClientOption(string option) - { - return string.Empty; - } - - public void SendScriptTeleportRequest (string objName, string simName, Vector3 pos, Vector3 lookAt) - { - } - - public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) - { - } - - public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) - { - } - - public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) - { - } - - public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) - { - } - - public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) - { - } - - public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) - { - } - - public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) - { - } - - public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) - { - } - - public void KillEndDone() - { - } - - public void SendEventInfoReply (EventData info) - { - } - - public void SendOfferCallingCard (UUID destID, UUID transactionID) - { - } - - public void SendAcceptCallingCard (UUID transactionID) - { - } - - public void SendDeclineCallingCard (UUID transactionID) - { - } - - public void SendJoinGroupReply(UUID groupID, bool success) - { - } - - public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) - { - } - - public void SendLeaveGroupReply(UUID groupID, bool success) - { - } - - public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) - { - } - - public void SendTerminateFriend(UUID exFriendID) - { - } - - #region IClientAPI Members - - - public bool AddGenericPacketHandler(string MethodName, GenericMessage handler) - { - throw new NotImplementedException(); - } - - public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) - { - } - - public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) - { - } - - public void SendAgentDropGroup(UUID groupID) - { - } - - public void SendAvatarNotesReply(UUID targetID, string text) - { - } - - public void SendAvatarPicksReply(UUID targetID, Dictionary picks) - { - } - - public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) - { - } - - public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) - { - } - - public void SendUserInfoReply(bool imViaEmail, bool visible, string email) - { - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs deleted file mode 100644 index 2e7b16c..0000000 --- a/OpenSim/Region/Environment/Modules/World/NPC/NPCModule.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenMetaverse; -using Nini.Config; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.NPC -{ - public class NPCModule : IRegionModule - { - // private const bool m_enabled = false; - - public void Initialise(Scene scene, IConfigSource source) - { - // if (m_enabled) - // { - // NPCAvatar testAvatar = new NPCAvatar("Jack", "NPC", new Vector3(128, 128, 40), scene); - // NPCAvatar testAvatar2 = new NPCAvatar("Jill", "NPC", new Vector3(136, 128, 40), scene); - // scene.AddNewClient(testAvatar, false); - // scene.AddNewClient(testAvatar2, false); - // } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "NPCModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs deleted file mode 100644 index 8838e39..0000000 --- a/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs +++ /dev/null @@ -1,1498 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenMetaverse; -using Nini.Config; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.Framework; -using OpenSim.Framework.Communications.Cache; - -namespace OpenSim.Region.Environment.Modules.World.Permissions -{ - public class PermissionsModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - - #region Constants - // These are here for testing. They will be taken out - - //private uint PERM_ALL = (uint)2147483647; - private uint PERM_COPY = (uint)32768; - //private uint PERM_MODIFY = (uint)16384; - private uint PERM_MOVE = (uint)524288; - //private uint PERM_TRANS = (uint)8192; - private uint PERM_LOCKED = (uint)540672; - - /// - /// Different user set names that come in from the configuration file. - /// - enum UserSet - { - All, - Administrators - }; - - #endregion - - #region Bypass Permissions / Debug Permissions Stuff - - // Bypasses the permissions engine - private bool m_bypassPermissions = true; - private bool m_bypassPermissionsValue = true; - private bool m_propagatePermissions = false; - private bool m_debugPermissions = false; - private bool m_allowGridGods = false; - private bool m_RegionOwnerIsGod = false; - private bool m_ParcelOwnerIsGod = false; - - /// - /// The set of users that are allowed to create scripts. This is only active if permissions are not being - /// bypassed. This overrides normal permissions. - /// - private UserSet m_allowedScriptCreators = UserSet.All; - - /// - /// The set of users that are allowed to edit (save) scripts. This is only active if - /// permissions are not being bypassed. This overrides normal permissions.- - /// - private UserSet m_allowedScriptEditors = UserSet.All; - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - - IConfig myConfig = config.Configs["Startup"]; - - string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); - - List modules=new List(permissionModules.Split(',')); - - if (!modules.Contains("DefaultPermissionsModule")) - return; - - m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false); - m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true); - m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true); - m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true); - m_ParcelOwnerIsGod = myConfig.GetBoolean("parcel_owner_is_god", true); - - m_allowedScriptCreators - = ParseUserSetConfigSetting(myConfig, "allowed_script_creators", m_allowedScriptCreators); - m_allowedScriptEditors - = ParseUserSetConfigSetting(myConfig, "allowed_script_editors", m_allowedScriptEditors); - - if (m_bypassPermissions) - m_log.Info("[PERMISSIONS]: serviceside_object_permissions = false in ini file so disabling all region service permission checks"); - else - m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); - - //Register functions with Scene External Checks! - m_scene.Permissions.AddBypassPermissionsHandler(BypassPermissions); //FULLY IMPLEMENTED - m_scene.Permissions.AddSetBypassPermissionsHandler(SetBypassPermissions); //FULLY IMPLEMENTED - m_scene.Permissions.AddPropagatePermissionsHandler(PropagatePermissions); //FULLY IMPLEMENTED - m_scene.Permissions.AddGenerateClientFlagsHandler(GenerateClientFlags); //NOT YET FULLY IMPLEMENTED - m_scene.Permissions.AddAbandonParcelHandler(CanAbandonParcel); //FULLY IMPLEMENTED - m_scene.Permissions.AddReclaimParcelHandler(CanReclaimParcel); //FULLY IMPLEMENTED - m_scene.Permissions.AddIsGodHandler(IsGod); //FULLY IMPLEMENTED - m_scene.Permissions.AddDuplicateObjectHandler(CanDuplicateObject); //FULLY IMPLEMENTED - m_scene.Permissions.AddDeleteObjectHandler(CanDeleteObject); //MAYBE FULLY IMPLEMENTED - m_scene.Permissions.AddEditObjectHandler(CanEditObject);//MAYBE FULLY IMPLEMENTED - m_scene.Permissions.AddEditParcelHandler(CanEditParcel); //FULLY IMPLEMENTED - m_scene.Permissions.AddInstantMessageHandler(CanInstantMessage); //FULLY IMPLEMENTED - m_scene.Permissions.AddInventoryTransferHandler(CanInventoryTransfer); //NOT YET IMPLEMENTED - m_scene.Permissions.AddIssueEstateCommandHandler(CanIssueEstateCommand); //FULLY IMPLEMENTED - m_scene.Permissions.AddMoveObjectHandler(CanMoveObject); //HOPEFULLY FULLY IMPLEMENTED - m_scene.Permissions.AddObjectEntryHandler(CanObjectEntry); //FULLY IMPLEMENTED - m_scene.Permissions.AddReturnObjectHandler(CanReturnObject); //NOT YET IMPLEMENTED - m_scene.Permissions.AddRezObjectHandler(CanRezObject); //HOPEFULLY FULLY IMPLEMENTED - m_scene.Permissions.AddRunConsoleCommandHandler(CanRunConsoleCommand); //FULLY IMPLEMENTED - m_scene.Permissions.AddRunScriptHandler(CanRunScript); //NOT YET IMPLEMENTED - m_scene.Permissions.AddSellParcelHandler(CanSellParcel); //FULLY IMPLEMENTED - m_scene.Permissions.AddTakeObjectHandler(CanTakeObject); //FULLY IMPLEMENTED - m_scene.Permissions.AddTakeCopyObjectHandler(CanTakeCopyObject); //FULLY IMPLEMENTED - m_scene.Permissions.AddTerraformLandHandler(CanTerraformLand); //FULL IMPLEMENTED (POINT ONLY!!! NOT AREA!!!) - m_scene.Permissions.AddCanLinkObjectHandler(CanLinkObject); //NOT YET IMPLEMENTED - m_scene.Permissions.AddCanDelinkObjectHandler(CanDelinkObject); //NOT YET IMPLEMENTED - m_scene.Permissions.AddCanBuyLandHandler(CanBuyLand); //NOT YET IMPLEMENTED - - m_scene.Permissions.AddViewNotecardHandler(CanViewNotecard); //NOT YET IMPLEMENTED - m_scene.Permissions.AddViewScriptHandler(CanViewScript); //NOT YET IMPLEMENTED - m_scene.Permissions.AddEditNotecardHandler(CanEditNotecard); //NOT YET IMPLEMENTED - m_scene.Permissions.AddEditScriptHandler(CanEditScript); //NOT YET IMPLEMENTED - - m_scene.Permissions.AddCanCreateObjectInventoryHandler(CanCreateObjectInventory); //NOT IMPLEMENTED HERE - m_scene.Permissions.AddEditObjectInventoryHandler(CanEditObjectInventory);//MAYBE FULLY IMPLEMENTED - m_scene.Permissions.AddCanCopyObjectInventoryHandler(CanCopyObjectInventory); //NOT YET IMPLEMENTED - m_scene.Permissions.AddCanDeleteObjectInventoryHandler(CanDeleteObjectInventory); //NOT YET IMPLEMENTED - m_scene.Permissions.AddResetScriptHandler(CanResetScript); - - m_scene.Permissions.AddCanCreateUserInventoryHandler(CanCreateUserInventory); //NOT YET IMPLEMENTED - m_scene.Permissions.AddCanCopyUserInventoryHandler(CanCopyUserInventory); //NOT YET IMPLEMENTED - m_scene.Permissions.AddCanEditUserInventoryHandler(CanEditUserInventory); //NOT YET IMPLEMENTED - m_scene.Permissions.AddCanDeleteUserInventoryHandler(CanDeleteUserInventory); //NOT YET IMPLEMENTED - - m_scene.Permissions.AddCanTeleportHandler(CanTeleport); //NOT YET IMPLEMENTED - - m_scene.AddCommand("permissions", "bypass permissions", - "bypass permissions ", - "Bypass permission checks", - HandleBypassPermissions); - - m_scene.AddCommand("permissions", "force permissions", - "force permissions ", - "Force permissions on or off", - HandleForcePermissions); - - m_scene.AddCommand("permissions", "debug permissions", - "debug permissions ", - "Enable permissions debugging", - HandleDebugPermissions); - } - - public void HandleBypassPermissions(string module, string[] args) - { - if (m_scene.ConsoleScene() != null && - m_scene.ConsoleScene() != m_scene) - { - return; - } - - if (args.Length > 2) - { - bool val; - - if (!bool.TryParse(args[2], out val)) - return; - - m_bypassPermissions = val; - - m_log.InfoFormat( - "[PERMISSIONS]: Set permissions bypass to {0} for {1}", - m_bypassPermissions, m_scene.RegionInfo.RegionName); - } - } - - public void HandleForcePermissions(string module, string[] args) - { - if (m_scene.ConsoleScene() != null && - m_scene.ConsoleScene() != m_scene) - { - return; - } - - if (!m_bypassPermissions) - { - m_log.Error("[PERMISSIONS] Permissions can't be forced unless they are bypassed first"); - return; - } - - if (args.Length > 2) - { - bool val; - - if (!bool.TryParse(args[2], out val)) - return; - - m_bypassPermissionsValue = val; - - m_log.InfoFormat("[PERMISSIONS] Forced permissions to {0} in {1}", m_bypassPermissionsValue, m_scene.RegionInfo.RegionName); - } - } - - public void HandleDebugPermissions(string module, string[] args) - { - if (m_scene.ConsoleScene() != null && - m_scene.ConsoleScene() != m_scene) - { - return; - } - - if (args.Length > 2) - { - bool val; - - if (!bool.TryParse(args[2], out val)) - return; - - m_debugPermissions = val; - - m_log.InfoFormat("[PERMISSIONS] Set permissions debugging to {0} in {1}", m_debugPermissions, m_scene.RegionInfo.RegionName); - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "PermissionsModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region Helper Functions - protected void SendPermissionError(UUID user, string reason) - { - m_scene.EventManager.TriggerPermissionError(user, reason); - } - - protected void DebugPermissionInformation(string permissionCalled) - { - if (m_debugPermissions) - m_log.Debug("[PERMISSIONS]: " + permissionCalled + " was called from " + m_scene.RegionInfo.RegionName); - } - - /// - /// Parse a user set configuration setting - /// - /// - /// - /// The default value for this attribute - /// The parsed value - private static UserSet ParseUserSetConfigSetting(IConfig config, string settingName, UserSet defaultValue) - { - UserSet userSet = defaultValue; - - string rawSetting = config.GetString(settingName, defaultValue.ToString()); - - // Temporary measure to allow 'gods' to be specified in config for consistency's sake. In the long term - // this should disappear. - if ("gods" == rawSetting.ToLower()) - rawSetting = UserSet.Administrators.ToString(); - - // Doing it this was so that we can do a case insensitive conversion - try - { - userSet = (UserSet)Enum.Parse(typeof(UserSet), rawSetting, true); - } - catch - { - m_log.ErrorFormat( - "[PERMISSIONS]: {0} is not a valid {1} value, setting to {2}", - rawSetting, settingName, userSet); - } - - m_log.DebugFormat("[PERMISSIONS]: {0} {1}", settingName, userSet); - - return userSet; - } - - /// - /// Is the given user an administrator (in other words, a god)? - /// - /// - /// - protected bool IsAdministrator(UUID user) - { - if (m_scene.RegionInfo.MasterAvatarAssignedUUID != UUID.Zero) - { - if (m_RegionOwnerIsGod && (m_scene.RegionInfo.MasterAvatarAssignedUUID == user)) - return true; - } - - if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) - { - if (m_scene.RegionInfo.EstateSettings.EstateOwner == user) - return true; - } - - if (m_allowGridGods) - { - CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(user); - if (profile != null && profile.UserProfile != null) - { - if (profile.UserProfile.GodLevel >= 200) - return true; - } - else - { - m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for administrator check", user); - } - } - - return false; - } - - protected bool IsEstateManager(UUID user) - { - return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); - } -#endregion - - public bool PropagatePermissions() - { - if (m_bypassPermissions) - return false; - - return m_propagatePermissions; - } - - public bool BypassPermissions() - { - return m_bypassPermissions; - } - - public void SetBypassPermissions(bool value) - { - m_bypassPermissions=value; - } - - #region Object Permissions - - public uint GenerateClientFlags(UUID user, UUID objID) - { - // Here's the way this works, - // ObjectFlags and Permission flags are two different enumerations - // ObjectFlags, however, tells the client to change what it will allow the user to do. - // So, that means that all of the permissions type ObjectFlags are /temporary/ and only - // supposed to be set when customizing the objectflags for the client. - - // These temporary objectflags get computed and added in this function based on the - // Permission mask that's appropriate! - // Outside of this method, they should never be added to objectflags! - // -teravus - - SceneObjectPart task = m_scene.GetSceneObjectPart(objID); - - // this shouldn't ever happen.. return no permissions/objectflags. - if (task == null) - return (uint)0; - - uint objflags = task.GetEffectiveObjectFlags(); - UUID objectOwner = task.OwnerID; - - - // Remove any of the objectFlags that are temporary. These will get added back if appropriate - // in the next bit of code - - // libomv will moan about PrimFlags.ObjectYouOfficer being - // deprecated - #pragma warning disable 0612 - objflags &= (uint) - ~(PrimFlags.ObjectCopy | // Tells client you can copy the object - PrimFlags.ObjectModify | // tells client you can modify the object - PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) - PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it - PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object - PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object - PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object - PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set - ); - #pragma warning restore 0612 - - // Creating the three ObjectFlags options for this method to choose from. - // Customize the OwnerMask - uint objectOwnerMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); - objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify; - - // Customize the GroupMask - // uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); - - // Customize the EveryoneMask - uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); - - - // Hack to allow collaboration until Groups and Group Permissions are implemented - if ((objectEveryoneMask & (uint)PrimFlags.ObjectMove) != 0) - objectEveryoneMask |= (uint)PrimFlags.ObjectModify; - - if (m_bypassPermissions) - return objectOwnerMask; - - // Object owners should be able to edit their own content - if (user == objectOwner) - { - return objectOwnerMask; - } - - // Users should be able to edit what is over their land. - ILandObject parcel = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); - if (parcel != null && parcel.landData.OwnerID == user && m_ParcelOwnerIsGod) - return objectOwnerMask; - - // Admin objects should not be editable by the above - if (IsAdministrator(objectOwner)) - return objectEveryoneMask; - - // Estate users should be able to edit anything in the sim - if (IsEstateManager(user) && m_RegionOwnerIsGod) - return objectOwnerMask; - - // Admin should be able to edit anything in the sim (including admin objects) - if (IsAdministrator(user)) - return objectOwnerMask; - - - return objectEveryoneMask; - } - - private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) - { - // We are adding the temporary objectflags to the object's objectflags based on the - // permission flag given. These change the F flags on the client. - - if ((setPermissionMask & (uint)PermissionMask.Copy) != 0) - { - objectFlagsMask |= (uint)PrimFlags.ObjectCopy; - } - - if ((setPermissionMask & (uint)PermissionMask.Move) != 0) - { - objectFlagsMask |= (uint)PrimFlags.ObjectMove; - } - - if ((setPermissionMask & (uint)PermissionMask.Modify) != 0) - { - objectFlagsMask |= (uint)PrimFlags.ObjectModify; - } - - if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0) - { - objectFlagsMask |= (uint)PrimFlags.ObjectTransfer; - } - - return objectFlagsMask; - } - - /// - /// General permissions checks for any operation involving an object. These supplement more specific checks - /// implemented by callers. - /// - /// - /// - /// - /// - protected bool GenericObjectPermission(UUID currentUser, UUID objId, bool denyOnLocked) - { - // Default: deny - bool permission = false; - bool locked = false; - - if (!m_scene.Entities.ContainsKey(objId)) - { - return false; - } - - // If it's not an object, we cant edit it. - if ((!(m_scene.Entities[objId] is SceneObjectGroup))) - { - return false; - } - - SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objId]; - - UUID objectOwner = group.OwnerID; - locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); - - // People shouldn't be able to do anything with locked objects, except the Administrator - // The 'set permissions' runs through a different permission check, so when an object owner - // sets an object locked, the only thing that they can do is unlock it. - // - // Nobody but the object owner can set permissions on an object - // - - if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) - { - return false; - } - - // Object owners should be able to edit their own content - if (currentUser == objectOwner) - { - permission = true; - } - else if (group.IsAttachment) - { - permission = false; - } - - // Users should be able to edit what is over their land. - ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); - if ((parcel != null) && (parcel.landData.OwnerID == currentUser)) - { - permission = true; - } - - // Estate users should be able to edit anything in the sim - if (IsEstateManager(currentUser)) - { - permission = true; - } - - // Admin objects should not be editable by the above - if (IsAdministrator(objectOwner)) - { - permission = false; - } - - // Admin should be able to edit anything in the sim (including admin objects) - if (IsAdministrator(currentUser)) - { - permission = true; - } - - return permission; - } - - #endregion - - #region Generic Permissions - protected bool GenericCommunicationPermission(UUID user, UUID target) - { - // Setting this to true so that cool stuff can happen until we define what determines Generic Communication Permission - bool permission = true; - string reason = "Only registered users may communicate with another account."; - - // Uhh, we need to finish this before we enable it.. because it's blocking all sorts of goodies and features - if (IsAdministrator(user)) - permission = true; - - if (IsEstateManager(user)) - permission = true; - - if (!permission) - SendPermissionError(user, reason); - - return permission; - } - - public bool GenericEstatePermission(UUID user) - { - // Default: deny - bool permission = false; - - // Estate admins should be able to use estate tools - if (IsEstateManager(user)) - permission = true; - - // Administrators always have permission - if (IsAdministrator(user)) - permission = true; - - return permission; - } - - protected bool GenericParcelPermission(UUID user, ILandObject parcel) - { - bool permission = false; - - if (parcel.landData.OwnerID == user) - { - permission = true; - } - - if (parcel.landData.IsGroupOwned) - { - // TODO: Need to do some extra checks here. Requires group code. - } - - if (IsEstateManager(user)) - { - permission = true; - } - - if (IsAdministrator(user)) - { - permission = true; - } - - return permission; - } - - protected bool GenericParcelPermission(UUID user, Vector3 pos) - { - ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); - if (parcel == null) return false; - return GenericParcelPermission(user, parcel); - } -#endregion - - #region Permission Checks - private bool CanAbandonParcel(UUID user, ILandObject parcel, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericParcelPermission(user, parcel); - } - - private bool CanReclaimParcel(UUID user, ILandObject parcel, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericParcelPermission(user, parcel); - } - - private bool IsGod(UUID user, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return IsAdministrator(user); - } - - private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if (!GenericObjectPermission(owner, objectID, true)) - { - //They can't even edit the object - return false; - } - - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - if (part == null) - return false; - - if ((part.OwnerMask & PERM_COPY) == 0) - return false; - - if ((part.ParentGroup.GetEffectivePermissions() & PERM_COPY) == 0) - return false; - - //If they can rez, they can duplicate - return CanRezObject(objectCount, owner, objectPosition, scene); - } - - private bool CanDeleteObject(UUID objectID, UUID deleter, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericObjectPermission(deleter, objectID, false); - } - - private bool CanEditObject(UUID objectID, UUID editorID, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - - return GenericObjectPermission(editorID, objectID, false); - } - - private bool CanEditObjectInventory(UUID objectID, UUID editorID, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); - - // If we selected a sub-prim to edit, the objectID won't represent the object, but only a part. - // We have to check the permissions of the group, though. - if (part.ParentID != 0) - { - objectID = part.ParentUUID; - part = m_scene.GetSceneObjectPart(objectID); - } - - // TODO: add group support! - // - if (part.OwnerID != editorID) - return false; - - return GenericObjectPermission(editorID, objectID, false); - } - - private bool CanEditParcel(UUID user, ILandObject parcel, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericParcelPermission(user, parcel); - } - - /// - /// Check whether the specified user can edit the given script - /// - /// - /// - /// - /// - /// - private bool CanEditScript(UUID script, UUID objectID, UUID user, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(user)) - return false; - - // Ordinarily, if you can view it, you can edit it - // There is no viewing a no mod script - // - return CanViewScript(script, objectID, user, scene); - } - - /// - /// Check whether the specified user can edit the given notecard - /// - /// - /// - /// - /// - /// - private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if (objectID == UUID.Zero) // User inventory - { - CachedUserInfo userInfo = - scene.CommsManager.UserProfileCacheService.GetUserDetails(user); - - if (userInfo == null) - { - m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for edit notecard check", user); - return false; - } - - if (userInfo.RootFolder == null) - return false; - - InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(notecard); - if (assetRequestItem == null) // Library item - { - assetRequestItem = scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(notecard); - - if (assetRequestItem != null) // Implicitly readable - return true; - } - - // Notecards must be both mod and copy to be saveable - // This is because of they're not copy, you can't read - // them, and if they're not mod, well, then they're - // not mod. Duh. - // - if ((assetRequestItem.CurrentPermissions & - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy)) != - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy)) - return false; - } - else // Prim inventory - { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - - if (part == null) - return false; - - if (part.OwnerID != user) - return false; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return false; - - TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); - - if (ti == null) - return false; - - if (ti.OwnerID != user) - return false; - - // Require full perms - if ((ti.CurrentPermissions & - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy)) != - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy)) - return false; - } - - return true; - } - - private bool CanInstantMessage(UUID user, UUID target, Scene startScene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - // If the sender is an object, check owner instead - // - SceneObjectPart part = startScene.GetSceneObjectPart(user); - if (part != null) - user = part.OwnerID; - - return GenericCommunicationPermission(user, target); - } - - private bool CanInventoryTransfer(UUID user, UUID target, Scene startScene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericCommunicationPermission(user, target); - } - - private bool CanIssueEstateCommand(UUID user, Scene requestFromScene, bool ownerCommand) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if (IsAdministrator(user)) - return true; - - if (m_scene.RegionInfo.EstateSettings.IsEstateOwner(user)) - return true; - - if (ownerCommand) - return false; - - return GenericEstatePermission(user); - } - - private bool CanMoveObject(UUID objectID, UUID moverID, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) - { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - if (part.OwnerID != moverID) - { - if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) - { - if (part.ParentGroup.IsAttachment) - return false; - } - } - return m_bypassPermissionsValue; - } - - bool permission = GenericObjectPermission(moverID, objectID, true); - if (!permission) - { - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } - - // The client - // may request to edit linked parts, and therefore, it needs - // to also check for SceneObjectPart - - // If it's not an object, we cant edit it. - if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) - { - return false; - } - - - SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; - - - // UUID taskOwner = null; - // Added this because at this point in time it wouldn't be wise for - // the administrator object permissions to take effect. - // UUID objectOwner = task.OwnerID; - - // Anyone can move - if ((task.RootPart.EveryoneMask & PERM_MOVE) != 0) - permission = true; - - // Locked - if ((task.RootPart.OwnerMask & PERM_LOCKED) == 0) - permission = false; - } - else - { - bool locked = false; - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } - - // If it's not an object, we cant edit it. - if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) - { - return false; - } - - SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objectID]; - - UUID objectOwner = group.OwnerID; - locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); - - // This is an exception to the generic object permission. - // Administrators who lock their objects should not be able to move them, - // however generic object permission should return true. - // This keeps locked objects from being affected by random click + drag actions by accident - // and allows the administrator to grab or delete a locked object. - - // Administrators and estate managers are still able to click+grab locked objects not - // owned by them in the scene - // This is by design. - - if (locked && (moverID == objectOwner)) - return false; - } - return permission; - } - - private bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if ((newPoint.X > 257f || newPoint.X < -1f || newPoint.Y > 257f || newPoint.Y < -1f)) - { - return true; - } - - SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; - - ILandObject land = m_scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); - - if (!enteringRegion) - { - ILandObject fromland = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); - - if (fromland == land) // Not entering - return true; - } - - if (land == null) - { - return false; - } - - if ((land.landData.Flags & ((int)Parcel.ParcelFlags.AllowAPrimitiveEntry)) != 0) - { - return true; - } - - //TODO: check for group rights - - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } - - // If it's not an object, we cant edit it. - if (!(m_scene.Entities[objectID] is SceneObjectGroup)) - { - return false; - } - - - if (GenericParcelPermission(task.OwnerID, newPoint)) - { - return true; - } - - //Otherwise, false! - return false; - } - - private bool CanReturnObject(UUID objectID, UUID returnerID, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericObjectPermission(returnerID, objectID, false); - } - - private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - bool permission = false; - - ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); - if (land == null) return false; - - if ((land.landData.Flags & ((int)Parcel.ParcelFlags.CreateObjects)) == - (int)Parcel.ParcelFlags.CreateObjects) - permission = true; - - //TODO: check for group rights - - if (IsAdministrator(owner)) - { - permission = true; - } - - if (GenericParcelPermission(owner, objectPosition)) - { - permission = true; - } - - return permission; - } - - private bool CanRunConsoleCommand(UUID user, Scene requestFromScene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - - return IsAdministrator(user); - } - - private bool CanRunScript(UUID script, UUID objectID, UUID user, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - private bool CanSellParcel(UUID user, ILandObject parcel, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericParcelPermission(user, parcel); - } - - private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return GenericObjectPermission(stealer,objectID, false); - } - - private bool CanTakeCopyObject(UUID objectID, UUID userID, Scene inScene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - bool permission = GenericObjectPermission(userID, objectID,false); - if (!permission) - { - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } - - // If it's not an object, we cant edit it. - if (!(m_scene.Entities[objectID] is SceneObjectGroup)) - { - return false; - } - - SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; - // UUID taskOwner = null; - // Added this because at this point in time it wouldn't be wise for - // the administrator object permissions to take effect. - // UUID objectOwner = task.OwnerID; - - if ((task.RootPart.EveryoneMask & PERM_COPY) != 0) - permission = true; - - if ((task.GetEffectivePermissions() & PERM_COPY) == 0) - permission = false; - } - else - { - SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; - - if ((task.GetEffectivePermissions() & PERM_COPY) == 0) - permission = false; - } - - return permission; - } - - private bool CanTerraformLand(UUID user, Vector3 position, Scene requestFromScene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - // Estate override - if (GenericEstatePermission(user)) - return true; - - float X = position.X; - float Y = position.Y; - - if (X > 255) - X = 255; - if (Y > 255) - Y = 255; - if (X < 0) - X = 0; - if (Y < 0) - Y = 0; - - ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y); - if (parcel == null) - return false; - - // Others allowed to terraform? - if ((parcel.landData.Flags & ((int)Parcel.ParcelFlags.AllowTerraform)) != 0) - return true; - - // Land owner can terraform too - if (parcel != null && GenericParcelPermission(user, parcel)) - return true; - - return false; - } - - /// - /// Check whether the specified user can view the given script - /// - /// - /// - /// - /// - /// - private bool CanViewScript(UUID script, UUID objectID, UUID user, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if (objectID == UUID.Zero) // User inventory - { - CachedUserInfo userInfo = - scene.CommsManager.UserProfileCacheService.GetUserDetails(user); - - if (userInfo == null) - { - m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for administrator check", user); - return false; - } - - if (userInfo.RootFolder == null) - return false; - - InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(script); - if (assetRequestItem == null) // Library item - { - assetRequestItem = m_scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(script); - - if (assetRequestItem != null) // Implicitly readable - return true; - } - - // SL is rather harebrained here. In SL, a script you - // have mod/copy no trans is readable. This subverts - // permissions, but is used in some products, most - // notably Hippo door plugin and HippoRent 5 networked - // prim counter. - // To enable this broken SL-ism, remove Transfer from - // the below expressions. - // Trying to improve on SL perms by making a script - // readable only if it's really full perms - // - if ((assetRequestItem.CurrentPermissions & - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer)) != - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer)) - return false; - } - else // Prim inventory - { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - - if (part == null) - return false; - - if (part.OwnerID != user) - return false; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return false; - - TaskInventoryItem ti = part.Inventory.GetInventoryItem(script); - - if (ti == null) - return false; - - if (ti.OwnerID != user) - return false; - - // Require full perms - if ((ti.CurrentPermissions & - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer)) != - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer)) - return false; - } - - return true; - } - - /// - /// Check whether the specified user can view the given notecard - /// - /// - /// - /// - /// - /// - private bool CanViewNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if (objectID == UUID.Zero) // User inventory - { - CachedUserInfo userInfo = - scene.CommsManager.UserProfileCacheService.GetUserDetails(user); - - if (userInfo == null) - { - m_log.ErrorFormat("[PERMISSIONS]: Could not find user {0} for view notecard check", user); - return false; - } - - if (userInfo.RootFolder == null) - return false; - - InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(notecard); - if (assetRequestItem == null) // Library item - { - assetRequestItem = m_scene.CommsManager.UserProfileCacheService.LibraryRoot.FindItem(notecard); - - if (assetRequestItem != null) // Implicitly readable - return true; - } - - // Notecards are always readable unless no copy - // - if ((assetRequestItem.CurrentPermissions & - (uint)PermissionMask.Copy) != - (uint)PermissionMask.Copy) - return false; - } - else // Prim inventory - { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - - if (part == null) - return false; - - if (part.OwnerID != user) - return false; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return false; - - TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); - - if (ti == null) - return false; - - if (ti.OwnerID != user) - return false; - - // Notecards are always readable unless no copy - // - if ((ti.CurrentPermissions & - (uint)PermissionMask.Copy) != - (uint)PermissionMask.Copy) - return false; - } - - return true; - } - - #endregion - - private bool CanLinkObject(UUID userID, UUID objectID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - private bool CanDelinkObject(UUID userID, UUID objectID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - private bool CanCopyObjectInventory(UUID itemID, UUID objectID, UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - private bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - /// - /// Check whether the specified user is allowed to directly create the given inventory type in a prim's - /// inventory (e.g. the New Script button in the 1.21 Linden Lab client). - /// - /// - /// - /// - /// - private bool CanCreateObjectInventory(int invType, UUID objectID, UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if ((int)InventoryType.LSL == invType) - if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID)) - return false; - - return true; - } - - /// - /// Check whether the specified user is allowed to create the given inventory type in their inventory. - /// - /// - /// - /// - private bool CanCreateUserInventory(int invType, UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - if ((int)InventoryType.LSL == invType) - if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID)) - return false; - - return true; - } - - /// - /// Check whether the specified user is allowed to copy the given inventory type in their inventory. - /// - /// - /// - /// - private bool CanCopyUserInventory(UUID itemID, UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - /// - /// Check whether the specified user is allowed to edit the given inventory item within their own inventory. - /// - /// - /// - /// - private bool CanEditUserInventory(UUID itemID, UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - /// - /// Check whether the specified user is allowed to delete the given inventory item from their own inventory. - /// - /// - /// - /// - private bool CanDeleteUserInventory(UUID itemID, UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - private bool CanTeleport(UUID userID) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - return true; - } - - private bool CanResetScript(UUID prim, UUID script, UUID agentID, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - SceneObjectPart part = m_scene.GetSceneObjectPart(prim); - - // If we selected a sub-prim to reset, prim won't represent the object, but only a part. - // We have to check the permissions of the object, though. - if (part.ParentID != 0) prim = part.ParentUUID; - - // You can reset the scripts in any object you can edit - return GenericObjectPermission(agentID, prim, false); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs deleted file mode 100644 index afad3cf..0000000 --- a/OpenSim/Region/Environment/Modules/World/Serialiser/IFileSerialiser.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Serialiser -{ - internal interface IFileSerialiser - { - string WriteToFile(Scene scene, string dir); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs deleted file mode 100644 index 8b3f2ce..0000000 --- a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseObjects.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Text; -using System.Xml; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Serialiser -{ - internal class SerialiseObjects : IFileSerialiser - { - #region IFileSerialiser Members - - public string WriteToFile(Scene scene, string dir) - { - string targetFileName = dir + "objects.xml"; - - SaveSerialisedToFile(targetFileName, scene); - - return "objects.xml"; - } - - #endregion - - public void SaveSerialisedToFile(string fileName, Scene scene) - { - string xmlstream = GetObjectXml(scene); - - MemoryStream stream = ReformatXmlString(xmlstream); - - stream.Seek(0, SeekOrigin.Begin); - CreateXmlFile(stream, fileName); - - stream.Seek(0, SeekOrigin.Begin); - CreateCompressedXmlFile(stream, fileName); - } - - private static MemoryStream ReformatXmlString(string xmlstream) - { - MemoryStream stream = new MemoryStream(); - XmlTextWriter formatter = new XmlTextWriter(stream, Encoding.UTF8); - XmlDocument doc = new XmlDocument(); - - doc.LoadXml(xmlstream); - formatter.Formatting = Formatting.Indented; - doc.WriteContentTo(formatter); - formatter.Flush(); - return stream; - } - - private static string GetObjectXml(Scene scene) - { - string xmlstream = ""; - - List EntityList = scene.GetEntities(); - List EntityXml = new List(); - - foreach (EntityBase ent in EntityList) - { - if (ent is SceneObjectGroup) - { - EntityXml.Add(((SceneObjectGroup) ent).ToXmlString2()); - } - } - EntityXml.Sort(); - - foreach (string xml in EntityXml) - xmlstream += xml; - - xmlstream += ""; - return xmlstream; - } - - private static void CreateXmlFile(MemoryStream xmlStream, string fileName) - { - FileStream objectsFile = new FileStream(fileName, FileMode.Create); - - xmlStream.WriteTo(objectsFile); - objectsFile.Flush(); - objectsFile.Close(); - } - - private static void CreateCompressedXmlFile(MemoryStream xmlStream, string fileName) - { - #region GZip Compressed Version - - FileStream objectsFileCompressed = new FileStream(fileName + ".gzs", FileMode.Create); - MemoryStream gzipMSStream = new MemoryStream(); - GZipStream gzipStream = new GZipStream(gzipMSStream, CompressionMode.Compress); - xmlStream.WriteTo(gzipStream); - gzipMSStream.WriteTo(objectsFileCompressed); - objectsFileCompressed.Flush(); - objectsFileCompressed.Close(); - - #endregion - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs deleted file mode 100644 index d0ce3d8..0000000 --- a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiseTerrain.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Environment.Modules.World.Terrain; -using OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Serialiser -{ - internal class SerialiseTerrain : IFileSerialiser - { - #region IFileSerialiser Members - - public string WriteToFile(Scene scene, string dir) - { - ITerrainLoader fileSystemExporter = new RAW32(); - string targetFileName = dir + "heightmap.r32"; - - lock (scene.Heightmap) - { - fileSystemExporter.SaveFile(targetFileName, scene.Heightmap); - } - - return "heightmap.r32"; - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs b/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs deleted file mode 100644 index 0e7873c..0000000 --- a/OpenSim/Region/Environment/Modules/World/Serialiser/SerialiserModule.cs +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using OpenMetaverse; -using Nini.Config; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.Framework.InterfaceCommander; - -namespace OpenSim.Region.Environment.Modules.World.Serialiser -{ - public class SerialiserModule : IRegionModule, IRegionSerialiserModule - { - private Commander m_commander = new Commander("export"); - private List m_regions = new List(); - private string m_savedir = "exports" + "/"; - private List m_serialisers = new List(); - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - scene.RegisterModuleCommander(m_commander); - scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; - scene.RegisterModuleInterface(this); - - lock (m_regions) - { - m_regions.Add(scene); - } - } - - public void PostInitialise() - { - lock (m_serialisers) - { - m_serialisers.Add(new SerialiseTerrain()); - m_serialisers.Add(new SerialiseObjects()); - } - - LoadCommanderCommands(); - } - - public void Close() - { - m_regions.Clear(); - } - - public string Name - { - get { return "ExportSerialisationModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region IRegionSerialiser Members - - public void LoadPrimsFromXml(Scene scene, string fileName, bool newIDS, Vector3 loadOffset) - { - SceneXmlLoader.LoadPrimsFromXml(scene, fileName, newIDS, loadOffset); - } - - public void SavePrimsToXml(Scene scene, string fileName) - { - SceneXmlLoader.SavePrimsToXml(scene, fileName); - } - - public void LoadPrimsFromXml2(Scene scene, string fileName) - { - SceneXmlLoader.LoadPrimsFromXml2(scene, fileName); - } - - public void LoadPrimsFromXml2(Scene scene, TextReader reader, bool startScripts) - { - SceneXmlLoader.LoadPrimsFromXml2(scene, reader, startScripts); - } - - public void SavePrimsToXml2(Scene scene, string fileName) - { - SceneXmlLoader.SavePrimsToXml2(scene, fileName); - } - - public void SavePrimsToXml2(Scene scene, TextWriter stream, Vector3 min, Vector3 max) - { - SceneXmlLoader.SavePrimsToXml2(scene, stream, min, max); - } - - public void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName) - { - SceneXmlLoader.SaveNamedPrimsToXml2(scene, primName, fileName); - } - - public SceneObjectGroup DeserializeGroupFromXml2(string xmlString) - { - return SceneXmlLoader.DeserializeGroupFromXml2(xmlString); - } - - public string SaveGroupToXml2(SceneObjectGroup grp) - { - return SceneXmlLoader.SaveGroupToXml2(grp); - } - - public void SavePrimListToXml2(List entityList, string fileName) - { - SceneXmlLoader.SavePrimListToXml2(entityList, fileName); - } - - public void SavePrimListToXml2(List entityList, TextWriter stream, Vector3 min, Vector3 max) - { - SceneXmlLoader.SavePrimListToXml2(entityList, stream, min, max); - } - - public List SerialiseRegion(Scene scene, string saveDir) - { - List results = new List(); - - if (!Directory.Exists(saveDir)) - { - Directory.CreateDirectory(saveDir); - } - - lock (m_serialisers) - { - foreach (IFileSerialiser serialiser in m_serialisers) - { - results.Add(serialiser.WriteToFile(scene, saveDir)); - } - } - - TextWriter regionInfoWriter = new StreamWriter(saveDir + "README.TXT"); - regionInfoWriter.WriteLine("Region Name: " + scene.RegionInfo.RegionName); - regionInfoWriter.WriteLine("Region ID: " + scene.RegionInfo.RegionID.ToString()); - regionInfoWriter.WriteLine("Backup Time: UTC " + DateTime.UtcNow.ToString()); - regionInfoWriter.WriteLine("Serialise Version: 0.1"); - regionInfoWriter.Close(); - - TextWriter manifestWriter = new StreamWriter(saveDir + "region.manifest"); - foreach (string line in results) - { - manifestWriter.WriteLine(line); - } - manifestWriter.Close(); - - return results; - } - - #endregion - - private void EventManager_OnPluginConsole(string[] args) - { - if (args[0] == "export") - { - string[] tmpArgs = new string[args.Length - 2]; - int i = 0; - for (i = 2; i < args.Length; i++) - tmpArgs[i - 2] = args[i]; - - m_commander.ProcessConsoleCommand(args[1], tmpArgs); - } - } - - private void InterfaceSaveRegion(Object[] args) - { - foreach (Scene region in m_regions) - { - if (region.RegionInfo.RegionName == (string) args[0]) - { - // List results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); - SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); - } - } - } - - private void InterfaceSaveAllRegions(Object[] args) - { - foreach (Scene region in m_regions) - { - // List results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); - SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); - } - } - - private void LoadCommanderCommands() - { - Command serialiseSceneCommand = new Command("save", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveRegion, "Saves the named region into the exports directory."); - serialiseSceneCommand.AddArgument("region-name", "The name of the region you wish to export", "String"); - - Command serialiseAllScenesCommand = new Command("save-all",CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveAllRegions, "Saves all regions into the exports directory."); - - m_commander.RegisterCommand("save", serialiseSceneCommand); - m_commander.RegisterCommand("save-all", serialiseAllScenesCommand); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs b/OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs deleted file mode 100644 index 1713797..0000000 --- a/OpenSim/Region/Environment/Modules/World/Sound/SoundModule.cs +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using Nini.Config; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.World.Sound -{ - public class SoundModule : IRegionModule, ISoundModule - { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - - m_scene.EventManager.OnNewClient += OnNewClient; - - m_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() {} - public void Close() {} - public string Name { get { return "Sound Module"; } } - public bool IsSharedModule { get { return false; } } - - private void OnNewClient(IClientAPI client) - { - client.OnSoundTrigger += TriggerSound; - } - - public virtual void PlayAttachedSound( - UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags) - { - foreach (ScenePresence p in m_scene.GetAvatars()) - { - double dis = Util.GetDistanceTo(p.AbsolutePosition, position); - if (dis > 100.0) // Max audio distance - continue; - - // Scale by distance - gain = (float)((double)gain*((100.0 - dis) / 100.0)); - - p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); - } - } - - public virtual void TriggerSound( - UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle) - { - foreach (ScenePresence p in m_scene.GetAvatars()) - { - double dis = Util.GetDistanceTo(p.AbsolutePosition, position); - if (dis > 100.0) // Max audio distance - continue; - - // Scale by distance - gain = (float)((double)gain*((100.0 - dis) / 100.0)); - - p.ControllingClient.SendTriggeredSound( - soundId, ownerID, objectID, parentID, handle, position, (float)gain); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs b/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs deleted file mode 100644 index ee96d58..0000000 --- a/OpenSim/Region/Environment/Modules/World/Sun/SunModule.cs +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class SunModule : IRegionModule - { - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - private const double SeasonalTilt = 0.03 * Math.PI; // A daily shift of approximately 1.7188 degrees - private const double AverageTilt = -0.25 * Math.PI; // A 45 degree tilt - private const double SunCycle = 2.0D * Math.PI; // A perfect circle measured in radians - private const double SeasonalCycle = 2.0D * Math.PI; // Ditto - - // - // Per Region Values - // - - private bool ready = false; - - // Configurable values - private string m_mode = "SL"; - private int m_frame_mod = 0; - private double m_day_length = 0; - private int m_year_length = 0; - private double m_day_night = 0; - // private double m_longitude = 0; - // private double m_latitude = 0; - // Configurable defaults Defaults close to SL - private string d_mode = "SL"; - private int d_frame_mod = 100; // Every 10 seconds (actually less) - private double d_day_length = 4; // A VW day is 4 RW hours long - private int d_year_length = 60; // There are 60 VW days in a VW year - private double d_day_night = 0.45; // axis offset: ratio of light-to-dark, approx 1:3 - // private double d_longitude = -73.53; - // private double d_latitude = 41.29; - - // Frame counter - private uint m_frame = 0; - - // Cached Scene reference - private Scene m_scene = null; - - // Calculated Once in the lifetime of a region - private long TicksToEpoch; // Elapsed time for 1/1/1970 - private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds - private uint SecondsPerYear; // Length of a virtual year in RW seconds - private double SunSpeed; // Rate of passage in radians/second - private double SeasonSpeed; // Rate of change for seasonal effects - // private double HoursToRadians; // Rate of change for seasonal effects - private long TicksOffset = 0; // seconds offset from UTC - // Calculated every update - private float OrbitalPosition; // Orbital placement at a point in time - private double HorizonShift; // Axis offset to skew day and night - private double TotalDistanceTravelled; // Distance since beginning of time (in radians) - private double SeasonalOffset; // Seaonal variation of tilt - private float Magnitude; // Normal tilt - // private double VWTimeRatio; // VW time as a ratio of real time - - // Working values - private Vector3 Position = Vector3.Zero; - private Vector3 Velocity = Vector3.Zero; - private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f); - - private long LindenHourOffset = 0; - private bool sunFixed = false; - - private Dictionary m_rootAgents = new Dictionary(); - - // Current time in elapsed seconds since Jan 1st 1970 - private ulong CurrentTime - { - get { - return (ulong)(((System.DateTime.Now.Ticks) - TicksToEpoch + TicksOffset + LindenHourOffset)/10000000); - } - } - - private float GetLindenEstateHourFromCurrentTime() - { - float ticksleftover = ((float)CurrentTime) % ((float)SecondsPerSunCycle); - - float hour = (24 * (ticksleftover / SecondsPerSunCycle)) + 6; - - return hour; - } - - private void SetTimeByLindenHour(float LindenHour) - { - // Linden hour is 24 hours with a 6 hour offset. 6-30 - - if (LindenHour - 6 == 0) - { - LindenHourOffset = 0; - return; - } - - // Remove LindenHourOffset to calculate it from LocalTime - float ticksleftover = ((float)(((long)(CurrentTime * 10000000) - (long)LindenHourOffset)/ 10000000) % ((float)SecondsPerSunCycle)); - float hour = (24 * (ticksleftover / SecondsPerSunCycle)); - - float offsethours = 0; - - if (LindenHour - 6 > hour) - { - offsethours = hour + ((LindenHour-6) - hour); - } - else - { - offsethours = hour - (hour - (LindenHour - 6)); - } - //m_log.Debug("[OFFSET]: " + hour + " - " + LindenHour + " - " + offsethours.ToString()); - - LindenHourOffset = (long)((float)offsethours * (36000000000/m_day_length)); - m_log.Debug("[SUN]: Directive from the Estate Tools to set the sun phase to LindenHour " + GetLindenEstateHourFromCurrentTime().ToString()); - } - - // Called immediately after the module is loaded for a given region - // i.e. Immediately after instance creation. - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - - m_frame = 0; - - TimeZone local = TimeZone.CurrentTimeZone; - TicksOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks; - m_log.Debug("[SUN]: localtime offset is " + TicksOffset); - - // Align ticks with Second Life - - TicksToEpoch = new System.DateTime(1970,1,1).Ticks; - - // Just in case they don't have the stanzas - try - { - // Mode: determines how the sun is handled - m_mode = config.Configs["Sun"].GetString("mode", d_mode); - // Mode: determines how the sun is handled - // m_latitude = config.Configs["Sun"].GetDouble("latitude", d_latitude); - // Mode: determines how the sun is handled - // m_longitude = config.Configs["Sun"].GetDouble("longitude", d_longitude); - // Year length in days - m_year_length = config.Configs["Sun"].GetInt("year_length", d_year_length); - // Day length in decimal hours - m_day_length = config.Configs["Sun"].GetDouble("day_length", d_day_length); - // Day to Night Ratio - m_day_night = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night); - // Update frequency in frames - m_frame_mod = config.Configs["Sun"].GetInt("update_interval", d_frame_mod); - } - catch (Exception e) - { - m_log.Debug("[SUN]: Configuration access failed, using defaults. Reason: "+e.Message); - m_mode = d_mode; - m_year_length = d_year_length; - m_day_length = d_day_length; - m_day_night = d_day_night; - m_frame_mod = d_frame_mod; - // m_latitude = d_latitude; - // m_longitude = d_longitude; - } - - switch (m_mode) - { - case "T1": - default: - case "SL": - // Time taken to complete a cycle (day and season) - - SecondsPerSunCycle = (uint) (m_day_length * 60 * 60); - SecondsPerYear = (uint) (SecondsPerSunCycle*m_year_length); - - // Ration of real-to-virtual time - - // VWTimeRatio = 24/m_day_length; - - // Speed of rotation needed to complete a cycle in the - // designated period (day and season) - - SunSpeed = SunCycle/SecondsPerSunCycle; - SeasonSpeed = SeasonalCycle/SecondsPerYear; - - // Horizon translation - - HorizonShift = m_day_night; // Z axis translation - // HoursToRadians = (SunCycle/24)*VWTimeRatio; - - // Insert our event handling hooks - - scene.EventManager.OnFrame += SunUpdate; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; - scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnClientClosed += ClientLoggedOut; - scene.EventManager.OnEstateToolsTimeUpdate += EstateToolsTimeUpdate; - scene.EventManager.OnGetSunLindenHour += GetLindenEstateHourFromCurrentTime; - - ready = true; - - m_log.Debug("[SUN]: Mode is "+m_mode); - m_log.Debug("[SUN]: Initialization completed. Day is "+SecondsPerSunCycle+" seconds, and year is "+m_year_length+" days"); - m_log.Debug("[SUN]: Axis offset is "+m_day_night); - m_log.Debug("[SUN]: Positional data updated every "+m_frame_mod+" frames"); - - break; - } - } - - public void PostInitialise() - { - } - - public void Close() - { - ready = false; - - // Remove our hooks - m_scene.EventManager.OnFrame -= SunUpdate; - m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent; - m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - m_scene.EventManager.OnClientClosed -= ClientLoggedOut; - m_scene.EventManager.OnEstateToolsTimeUpdate -= EstateToolsTimeUpdate; - m_scene.EventManager.OnGetSunLindenHour -= GetLindenEstateHourFromCurrentTime; - } - - public string Name - { - get { return "SunModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void SunToClient(IClientAPI client) - { - if (m_mode != "T1") - { - if (ready) - { - if (!sunFixed) - GenSunPos(); // Generate shared values once - client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); - } - } - } - - public void SunUpdate() - { - if (((m_frame++%m_frame_mod) != 0) || !ready || sunFixed) - { - return; - } - - GenSunPos(); // Generate shared values once - - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence avatar in avatars) - { - if (!avatar.IsChildAgent) - avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); - } - - // set estate settings for region access to sun position - m_scene.RegionInfo.RegionSettings.SunVector = Position; - //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime(); - } - - public void ForceSunUpdateToAllClients() - { - GenSunPos(); // Generate shared values once - - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence avatar in avatars) - { - if (!avatar.IsChildAgent) - avatar.ControllingClient.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); - } - - // set estate settings for region access to sun position - m_scene.RegionInfo.RegionSettings.SunVector = Position; - m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime(); - } - - /// - /// Calculate the sun's orbital position and its velocity. - /// - private void GenSunPos() - { - TotalDistanceTravelled = SunSpeed * CurrentTime; // distance measured in radians - OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); // position measured in radians - - // TotalDistanceTravelled += HoursToRadians-(0.25*Math.PI)*Math.Cos(HoursToRadians)-OrbitalPosition; - // OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); - - SeasonalOffset = SeasonSpeed * CurrentTime; // Present season determined as total radians travelled around season cycle - - Tilt.W = (float) (AverageTilt + (SeasonalTilt*Math.Sin(SeasonalOffset))); // Calculate seasonal orbital N/S tilt - - // m_log.Debug("[SUN] Total distance travelled = "+TotalDistanceTravelled+", present position = "+OrbitalPosition+"."); - // m_log.Debug("[SUN] Total seasonal progress = "+SeasonalOffset+", present tilt = "+Tilt.W+"."); - - // The sun rotates about the Z axis - - Position.X = (float) Math.Cos(-TotalDistanceTravelled); - Position.Y = (float) Math.Sin(-TotalDistanceTravelled); - Position.Z = 0; - - // For interest we rotate it slightly about the X access. - // Celestial tilt is a value that ranges .025 - - Position *= Tilt; - - // Finally we shift the axis so that more of the - // circle is above the horizon than below. This - // makes the nights shorter than the days. - - Position.Z = Position.Z + (float) HorizonShift; - Position = Vector3.Normalize(Position); - - // m_log.Debug("[SUN] Position("+Position.X+","+Position.Y+","+Position.Z+")"); - - Velocity.X = 0; - Velocity.Y = 0; - Velocity.Z = (float) SunSpeed; - - // Correct angular velocity to reflect the seasonal rotation - - Magnitude = Position.Length(); - if (sunFixed) - { - Velocity.X = 0; - Velocity.Y = 0; - Velocity.Z = 0; - return; - } - - Velocity = (Velocity * Tilt) * (1.0f / Magnitude); - - // m_log.Debug("[SUN] Velocity("+Velocity.X+","+Velocity.Y+","+Velocity.Z+")"); - } - - private void ClientLoggedOut(UUID AgentId) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(AgentId)) - { - m_rootAgents.Remove(AgentId); - } - } - } - - private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - m_rootAgents[avatar.UUID] = avatar.RegionHandle; - } - else - { - m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); - SunToClient(avatar.ControllingClient); - } - } - //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); - } - - private void MakeChildAgent(ScenePresence avatar) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) - { - m_rootAgents.Remove(avatar.UUID); - } - } - } - } - - public void EstateToolsTimeUpdate(ulong regionHandle, bool FixedTime, bool useEstateTime, float LindenHour) - { - if (m_scene.RegionInfo.RegionHandle == regionHandle) - { - SetTimeByLindenHour(LindenHour); - - //if (useEstateTime) - //LindenHourOffset = 0; - - ForceSunUpdateToAllClients(); - sunFixed = FixedTime; - if (sunFixed) - GenSunPos(); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs b/OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs deleted file mode 100644 index 83246fb..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/CookieCutter.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.Effects -{ - internal class CookieCutter : ITerrainEffect - { - #region ITerrainEffect Members - - public void RunEffect(ITerrainChannel map) - { - ITerrainPaintableEffect eroder = new WeatherSphere(); - - bool[,] cliffMask = new bool[map.Width,map.Height]; - bool[,] channelMask = new bool[map.Width,map.Height]; - bool[,] smoothMask = new bool[map.Width,map.Height]; - bool[,] allowMask = new bool[map.Width,map.Height]; - - Console.WriteLine("S1"); - - // Step one, generate rough mask - int x, y; - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - Console.Write("."); - smoothMask[x, y] = true; - allowMask[x,y] = true; - - // Start underwater - map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 5; - // Add a little height. (terrain should now be above water, mostly.) - map[x, y] += 20; - - const int channelsX = 4; - int channelWidth = (map.Width / channelsX / 4); - const int channelsY = 4; - int channelHeight = (map.Height / channelsY / 4); - - SetLowerChannel(map, cliffMask, channelMask, x, y, channelsX, channelWidth, map.Width, x); - SetLowerChannel(map, cliffMask, channelMask, x, y, channelsY, channelHeight, map.Height, y); - } - } - - Console.WriteLine("S2"); - //smooth.FloodEffect(map, smoothMask, 4.0); - - Console.WriteLine("S3"); - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - if (cliffMask[x, y]) - eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1); - } - } - - for (x = 0; x < map.Width; x += 2) - { - for (y = 0; y < map.Height; y += 2) - { - if (map[x, y] < 0.1) - map[x, y] = 0.1; - if (map[x, y] > 256) - map[x, y] = 256; - } - } - //smooth.FloodEffect(map, smoothMask, 4.0); - } - - #endregion - - private static void SetLowerChannel(ITerrainChannel map, bool[,] cliffMask, bool[,] channelMask, int x, int y, int numChannels, int channelWidth, - int mapSize, int rp) - { - for (int i = 0; i < numChannels; i++) - { - double distanceToLine = Math.Abs(rp - ((mapSize / numChannels) * i)); - - if (distanceToLine < channelWidth) - { - if (channelMask[x, y]) - return; - - // Remove channels - map[x, y] -= 10; - channelMask[x, y] = true; - } - if (distanceToLine < 1) - { - cliffMask[x, y] = true; - } - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs deleted file mode 100644 index 2082137..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/Effects/DefaultTerrainGenerator.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.Effects -{ - internal class DefaultTerrainGenerator : ITerrainEffect - { - #region ITerrainEffect Members - - public void RunEffect(ITerrainChannel map) - { - int x, y; - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10; - double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01; - if (map[x, y] < spherFac) - { - map[x, y] = spherFac; - } - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs deleted file mode 100644 index a8e79d0..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/BMP.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - /// - /// A generic windows bitmap loader. - /// Should be capable of handling 24-bit RGB images. - /// - /// Uses the System.Drawing filesystem loader. - /// - internal class BMP : GenericSystemDrawing - { - /// - /// Exports a file to a image on the disk using a System.Drawing exporter. - /// - /// The target filename - /// The terrain channel being saved - public override void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Bmp); - } - - /// - /// Exports a stream using a System.Drawing exporter. - /// - /// The target stream - /// The terrain channel being saved - public override void SaveStream(Stream stream, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(stream, ImageFormat.Png); - } - - /// - /// The human readable version of the file format(s) this loader handles - /// - /// - public override string ToString() - { - return "BMP"; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs deleted file mode 100644 index b76fe05..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GIF.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - internal class GIF : GenericSystemDrawing - { - public override void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Gif); - } - - /// - /// Exports a stream using a System.Drawing exporter. - /// - /// The target stream - /// The terrain channel being saved - public override void SaveStream(Stream stream, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(stream, ImageFormat.Gif); - } - - public override string ToString() - { - return "GIF"; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs deleted file mode 100644 index 80873d9..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - /// - /// A virtual class designed to have methods overloaded, - /// this class provides an interface for a generic image - /// saving and loading mechanism, but does not specify the - /// format. It should not be insubstantiated directly. - /// - public class GenericSystemDrawing : ITerrainLoader - { - #region ITerrainLoader Members - - public string FileExtension - { - get { return ".gsd"; } - } - - /// - /// Loads a file from a specified filename on the disk, - /// parses the image using the System.Drawing parsers - /// then returns a terrain channel. Values are - /// returned based on HSL brightness between 0m and 128m - /// - /// The target image to load - /// A terrain channel generated from the image. - public virtual ITerrainChannel LoadFile(string filename) - { - return LoadBitmap(new Bitmap(filename)); - } - - public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) - { - throw new NotImplementedException(); - } - - public virtual ITerrainChannel LoadStream(Stream stream) - { - return LoadBitmap(new Bitmap(stream)); - } - - protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap) - { - ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height); - - int x; - for (x = 0; x < bitmap.Width; x++) - { - int y; - for (y = 0; y < bitmap.Height; y++) - { - retval[x, y] = bitmap.GetPixel(x, bitmap.Height - y - 1).GetBrightness() * 128; - } - } - - return retval; - } - - /// - /// Exports a file to a image on the disk using a System.Drawing exporter. - /// - /// The target filename - /// The terrain channel being saved - public virtual void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Png); - } - - /// - /// Exports a stream using a System.Drawing exporter. - /// - /// The target stream - /// The terrain channel being saved - public virtual void SaveStream(Stream stream, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(stream, ImageFormat.Png); - } - - #endregion - - public override string ToString() - { - return "SYS.DRAWING"; - } - - /// - /// Protected method, generates a grayscale bitmap - /// image from a specified terrain channel. - /// - /// The terrain channel to export to bitmap - /// A System.Drawing.Bitmap containing a grayscale image - protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) - { - Bitmap bmp = new Bitmap(map.Width, map.Height); - - const int pallete = 256; - - Color[] grays = new Color[pallete]; - for (int i = 0; i < grays.Length; i++) - { - grays[i] = Color.FromArgb(i, i, i); - } - - for (int y = 0; y < map.Height; y++) - { - for (int x = 0; x < map.Width; x++) - { - // 512 is the largest possible height before colours clamp - int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 128.0), 0.0) * (pallete - 1)); - - // Handle error conditions - if (colorindex > pallete - 1 || colorindex < 0) - bmp.SetPixel(x, map.Height - y - 1, Color.Red); - else - bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]); - } - } - return bmp; - } - - /// - /// Protected method, generates a coloured bitmap - /// image from a specified terrain channel. - /// - /// The terrain channel to export to bitmap - /// A System.Drawing.Bitmap containing a coloured image - protected static Bitmap CreateBitmapFromMap(ITerrainChannel map) - { - Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); - - int pallete = gradientmapLd.Height; - - Bitmap bmp = new Bitmap(map.Width, map.Height); - Color[] colours = new Color[pallete]; - - for (int i = 0; i < pallete; i++) - { - colours[i] = gradientmapLd.GetPixel(0, i); - } - - for (int y = 0; y < map.Height; y++) - { - for (int x = 0; x < map.Width; x++) - { - // 512 is the largest possible height before colours clamp - int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1)); - - // Handle error conditions - if (colorindex > pallete - 1 || colorindex < 0) - bmp.SetPixel(x, map.Height - y - 1, Color.Red); - else - bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); - } - } - return bmp; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs deleted file mode 100644 index bea504d..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/JPEG.cs +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - public class JPEG : ITerrainLoader - { - #region ITerrainLoader Members - - public string FileExtension - { - get { return ".jpg"; } - } - - public ITerrainChannel LoadFile(string filename) - { - throw new NotImplementedException(); - } - - public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) - { - throw new NotImplementedException(); - } - - public ITerrainChannel LoadStream(Stream stream) - { - throw new NotImplementedException(); - } - - public void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Jpeg); - } - - /// - /// Exports a stream using a System.Drawing exporter. - /// - /// The target stream - /// The terrain channel being saved - public void SaveStream(Stream stream, ITerrainChannel map) - { - Bitmap colours = CreateBitmapFromMap(map); - - colours.Save(stream, ImageFormat.Jpeg); - } - - #endregion - - public override string ToString() - { - return "JPEG"; - } - - private static Bitmap CreateBitmapFromMap(ITerrainChannel map) - { - Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); - - int pallete = gradientmapLd.Height; - - Bitmap bmp = new Bitmap(map.Width, map.Height); - Color[] colours = new Color[pallete]; - - for (int i = 0; i < pallete; i++) - { - colours[i] = gradientmapLd.GetPixel(0, i); - } - - for (int y = 0; y < map.Height; y++) - { - for (int x = 0; x < map.Width; x++) - { - // 512 is the largest possible height before colours clamp - int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1)); - bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); - } - } - return bmp; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs deleted file mode 100644 index e323e28..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/LLRAW.cs +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - public class LLRAW : ITerrainLoader - { - public struct HeightmapLookupValue : IComparable - { - public int Index; - public double Value; - - public HeightmapLookupValue(int index, double value) - { - Index = index; - Value = value; - } - - public int CompareTo(HeightmapLookupValue val) - { - return Value.CompareTo(val.Value); - } - } - - /// Lookup table to speed up terrain exports - HeightmapLookupValue[] LookupHeightTable; - - public LLRAW() - { - LookupHeightTable = new HeightmapLookupValue[256 * 256]; - - for (int i = 0; i < 256; i++) - { - for (int j = 0; j < 256; j++) - { - LookupHeightTable[i + (j * 256)] = new HeightmapLookupValue(i + (j * 256), ((double)i * ((double)j / 128.0d))); - } - } - Array.Sort(LookupHeightTable); - } - - #region ITerrainLoader Members - - public ITerrainChannel LoadFile(string filename) - { - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - ITerrainChannel retval = LoadStream(s); - - s.Close(); - - return retval; - } - - public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight) - { - TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight); - - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - BinaryReader bs = new BinaryReader(s); - - int currFileYOffset = fileHeight - 1; - - // if our region isn't on the first Y section of the areas to be landscaped, then - // advance to our section of the file - while (currFileYOffset > offsetY) - { - // read a whole strip of regions - int heightsToRead = sectionHeight * (fileWidth * sectionWidth); - bs.ReadBytes(heightsToRead * 13); // because there are 13 fun channels - currFileYOffset--; - } - - // got to the Y start offset within the file of our region - // so read the file bits associated with our region - int y; - // for each Y within our Y offset - for (y = sectionHeight - 1; y >= 0; y--) - { - int currFileXOffset = 0; - - // if our region isn't the first X section of the areas to be landscaped, then - // advance the stream to the X start pos of our section in the file - // i.e. eat X upto where we start - while (currFileXOffset < offsetX) - { - bs.ReadBytes(sectionWidth * 13); - currFileXOffset++; - } - - // got to our X offset, so write our regions X line - int x; - for (x = 0; x < sectionWidth; x++) - { - // Read a strip and continue - retval[x, y] = bs.ReadByte() * (bs.ReadByte() / 128.0); - bs.ReadBytes(11); - } - // record that we wrote it - currFileXOffset++; - - // if our region isn't the last X section of the areas to be landscaped, then - // advance the stream to the end of this Y column - while (currFileXOffset < fileWidth) - { - // eat the next regions x line - bs.ReadBytes(sectionWidth * 13); //The 13 channels again - currFileXOffset++; - } - } - - bs.Close(); - s.Close(); - - return retval; - } - - public ITerrainChannel LoadStream(Stream s) - { - TerrainChannel retval = new TerrainChannel(); - - BinaryReader bs = new BinaryReader(s); - int y; - for (y = 0; y < retval.Height; y++) - { - int x; - for (x = 0; x < retval.Width; x++) - { - retval[x, (retval.Height - 1) - y] = bs.ReadByte() * (bs.ReadByte() / 128.0); - bs.ReadBytes(11); // Advance the stream to next bytes. - } - } - - bs.Close(); - - return retval; - } - - public void SaveFile(string filename, ITerrainChannel map) - { - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); - SaveStream(s, map); - - s.Close(); - } - - public void SaveStream(Stream s, ITerrainChannel map) - { - BinaryWriter binStream = new BinaryWriter(s); - - // Output the calculated raw - for (int y = 0; y < map.Height; y++) - { - for (int x = 0; x < map.Width; x++) - { - double t = map[x, (map.Height - 1) - y]; - //if height is less than 0, set it to 0 as - //can't save -ve values in a LLRAW file - if (t < 0d) - { - t = 0d; - } - - int index = 0; - - // The lookup table is pre-sorted, so we either find an exact match or - // the next closest (smaller) match with a binary search - index = Array.BinarySearch(LookupHeightTable, new HeightmapLookupValue(0, t)); - if (index < 0) - index = ~index - 1; - - index = LookupHeightTable[index].Index; - - byte red = (byte) (index & 0xFF); - byte green = (byte) ((index >> 8) & 0xFF); - const byte blue = 20; - const byte alpha1 = 0; - const byte alpha2 = 0; - const byte alpha3 = 0; - const byte alpha4 = 0; - const byte alpha5 = 255; - const byte alpha6 = 255; - const byte alpha7 = 255; - const byte alpha8 = 255; - byte alpha9 = red; - byte alpha10 = green; - - binStream.Write(red); - binStream.Write(green); - binStream.Write(blue); - binStream.Write(alpha1); - binStream.Write(alpha2); - binStream.Write(alpha3); - binStream.Write(alpha4); - binStream.Write(alpha5); - binStream.Write(alpha6); - binStream.Write(alpha7); - binStream.Write(alpha8); - binStream.Write(alpha9); - binStream.Write(alpha10); - } - } - - binStream.Close(); - } - - public string FileExtension - { - get { return ".raw"; } - } - - #endregion - - public override string ToString() - { - return "LL/SL RAW"; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs deleted file mode 100644 index 25967f3..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/PNG.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - internal class PNG : GenericSystemDrawing - { - public override void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Png); - } - - /// - /// Exports a stream using a System.Drawing exporter. - /// - /// The target stream - /// The terrain channel being saved - public override void SaveStream(Stream stream, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(stream, ImageFormat.Png); - } - - public override string ToString() - { - return "PNG"; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs deleted file mode 100644 index 7aff56a..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/RAW32.cs +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.IO; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - public class RAW32 : ITerrainLoader - { - #region ITerrainLoader Members - - public string FileExtension - { - get { return ".r32"; } - } - - public ITerrainChannel LoadFile(string filename) - { - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - ITerrainChannel retval = LoadStream(s); - - s.Close(); - - return retval; - } - - public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight) - { - TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight); - - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - BinaryReader bs = new BinaryReader(s); - - int currFileYOffset = 0; - - // if our region isn't on the first Y section of the areas to be landscaped, then - // advance to our section of the file - while (currFileYOffset < offsetY) - { - // read a whole strip of regions - int heightsToRead = sectionHeight * (fileWidth * sectionWidth); - bs.ReadBytes(heightsToRead * 4); // because the floats are 4 bytes in the file - currFileYOffset++; - } - - // got to the Y start offset within the file of our region - // so read the file bits associated with our region - int y; - // for each Y within our Y offset - for (y = 0; y < sectionHeight; y++) - { - int currFileXOffset = 0; - - // if our region isn't the first X section of the areas to be landscaped, then - // advance the stream to the X start pos of our section in the file - // i.e. eat X upto where we start - while (currFileXOffset < offsetX) - { - bs.ReadBytes(sectionWidth * 4); // 4 bytes = single - currFileXOffset++; - } - - // got to our X offset, so write our regions X line - int x; - for (x = 0; x < sectionWidth; x++) - { - // Read a strip and continue - retval[x, y] = bs.ReadSingle(); - } - // record that we wrote it - currFileXOffset++; - - // if our region isn't the last X section of the areas to be landscaped, then - // advance the stream to the end of this Y column - while (currFileXOffset < fileWidth) - { - // eat the next regions x line - bs.ReadBytes(sectionWidth * 4); // 4 bytes = single - currFileXOffset++; - } - } - - bs.Close(); - s.Close(); - - return retval; - } - - public ITerrainChannel LoadStream(Stream s) - { - TerrainChannel retval = new TerrainChannel(); - - BinaryReader bs = new BinaryReader(s); - int y; - for (y = 0; y < retval.Height; y++) - { - int x; - for (x = 0; x < retval.Width; x++) - { - retval[x, y] = bs.ReadSingle(); - } - } - - bs.Close(); - - return retval; - } - - public void SaveFile(string filename, ITerrainChannel map) - { - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Create, FileAccess.Write); - SaveStream(s, map); - - s.Close(); - } - - public void SaveStream(Stream s, ITerrainChannel map) - { - BinaryWriter bs = new BinaryWriter(s); - - int y; - for (y = 0; y < map.Height; y++) - { - int x; - for (x = 0; x < map.Width; x++) - { - bs.Write((float) map[x, y]); - } - } - - bs.Close(); - } - - #endregion - - public override string ToString() - { - return "RAW32"; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs deleted file mode 100644 index 0503487..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/TIFF.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - internal class TIFF : GenericSystemDrawing - { - public override void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Tiff); - } - - /// - /// Exports a stream using a System.Drawing exporter. - /// - /// The target stream - /// The terrain channel being saved - public override void SaveStream(Stream stream, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(stream, ImageFormat.Tiff); - } - - public override string ToString() - { - return "TIFF"; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs deleted file mode 100644 index 44d03e3..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FileLoaders/Terragen.cs +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Text; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders -{ - /// - /// Terragen File Format Loader - /// Built from specification at - /// http://www.planetside.co.uk/terragen/dev/tgterrain.html - /// - internal class Terragen : ITerrainLoader - { - #region ITerrainLoader Members - - public ITerrainChannel LoadFile(string filename) - { - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - ITerrainChannel retval = LoadStream(s); - - s.Close(); - - return retval; - } - - public ITerrainChannel LoadStream(Stream s) - { - TerrainChannel retval = new TerrainChannel(); - - BinaryReader bs = new BinaryReader(s); - - bool eof = false; - if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") - { - int w = 256; - int h = 256; - - // Terragen file - while (eof == false) - { - string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4)); - switch (tmp) - { - case "SIZE": - int sztmp = bs.ReadInt16() + 1; - w = sztmp; - h = sztmp; - bs.ReadInt16(); - break; - case "XPTS": - w = bs.ReadInt16(); - bs.ReadInt16(); - break; - case "YPTS": - h = bs.ReadInt16(); - bs.ReadInt16(); - break; - case "ALTW": - eof = true; - Int16 heightScale = bs.ReadInt16(); - Int16 baseHeight = bs.ReadInt16(); - retval = new TerrainChannel(w, h); - int x; - for (x = 0; x < w; x++) - { - int y; - for (y = 0; y < h; y++) - { - retval[x, y] = baseHeight + bs.ReadInt16() * (double) heightScale / 65536.0; - } - } - break; - default: - bs.ReadInt32(); - break; - } - } - } - - bs.Close(); - - return retval; - } - - public void SaveFile(string filename, ITerrainChannel map) - { - throw new NotImplementedException(); - } - - public void SaveStream(Stream stream, ITerrainChannel map) - { - throw new NotImplementedException(); - } - - public string FileExtension - { - get { return ".ter"; } - } - - public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) - { - throw new NotImplementedException(); - } - - #endregion - - public override string ToString() - { - return "Terragen"; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs deleted file mode 100644 index 4d49a70..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/FlattenArea.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes -{ - public class FlattenArea : ITerrainFloodEffect - { - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - double sum = 0.0; - double steps = 0.0; - - int x, y; - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - if (fillArea[x, y]) - { - sum += map[x, y]; - steps += 1.0; - } - } - } - - double avg = sum / steps; - - double str = 0.1 * strength; // == 0.2 in the default client - - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - if (fillArea[x, y]) - map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str); - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs deleted file mode 100644 index 64f9014..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/LowerArea.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes -{ - public class LowerArea : ITerrainFloodEffect - { - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - int x; - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (fillArea[x, y]) - { - map[x, y] -= strength; - } - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs deleted file mode 100644 index 2d44a3a..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/NoiseArea.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes -{ - public class NoiseArea : ITerrainFloodEffect - { - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - int x; - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (fillArea[x, y]) - { - double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0); - - map[x, y] += noise * strength; - } - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs deleted file mode 100644 index 0c7d016..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RaiseArea.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes -{ - public class RaiseArea : ITerrainFloodEffect - { - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - int x; - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (fillArea[x, y]) - { - map[x, y] += strength; - } - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs deleted file mode 100644 index 3f06d82..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/RevertArea.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes -{ - public class RevertArea : ITerrainFloodEffect - { - private readonly ITerrainChannel m_revertmap; - - public RevertArea(ITerrainChannel revertmap) - { - m_revertmap = revertmap; - } - - #region ITerrainFloodEffect Members - - /// - /// reverts an area of the map to the heightfield stored in the revertmap - /// - /// the current heightmap - /// array indicating which sections of the map are to be reverted - /// unused - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - int x; - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (fillArea[x, y]) - { - map[x, y] = m_revertmap[x, y]; - } - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs deleted file mode 100644 index 3881264..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/FloodBrushes/SmoothArea.cs +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes -{ - public class SmoothArea : ITerrainFloodEffect - { - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - double area = strength; - double step = strength / 4.0; - - double[,] manipulate = new double[map.Width,map.Height]; - int x, y; - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - if (!fillArea[x, y]) - continue; - - double average = 0.0; - int avgsteps = 0; - - double n; - for (n = 0.0 - area; n < area; n += step) - { - double l; - for (l = 0.0 - area; l < area; l += step) - { - avgsteps++; - average += GetBilinearInterpolate(x + n, y + l, map); - } - } - - manipulate[x, y] = average / avgsteps; - } - } - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - if (!fillArea[x, y]) - continue; - - map[x, y] = manipulate[x, y]; - } - } - } - - #endregion - - private static double GetBilinearInterpolate(double x, double y, ITerrainChannel map) - { - int w = map.Width; - int h = map.Height; - - if (x > w - 2.0) - x = w - 2.0; - if (y > h - 2.0) - y = h - 2.0; - if (x < 0.0) - x = 0.0; - if (y < 0.0) - y = 0.0; - - const int stepSize = 1; - double h00 = map[(int) x, (int) y]; - double h10 = map[(int) x + stepSize, (int) y]; - double h01 = map[(int) x, (int) y + stepSize]; - double h11 = map[(int) x + stepSize, (int) y + stepSize]; - double h1 = h00; - double h2 = h10; - double h3 = h01; - double h4 = h11; - double a00 = h1; - double a10 = h2 - h1; - double a01 = h3 - h1; - double a11 = h1 - h2 - h3 + h4; - double partialx = x - (int) x; - double partialz = y - (int) y; - double hi = a00 + (a10 * partialx) + (a01 * partialz) + (a11 * partialx * partialz); - return hi; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs deleted file mode 100644 index 4533e9e..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainEffect.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain -{ - public interface ITerrainEffect - { - void RunEffect(ITerrainChannel map); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs deleted file mode 100644 index 5bae84b..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainFloodEffect.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain -{ - public interface ITerrainFloodEffect - { - void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs deleted file mode 100644 index 21bda58..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainLoader.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.IO; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain -{ - public interface ITerrainLoader - { - string FileExtension { get; } - ITerrainChannel LoadFile(string filename); - ITerrainChannel LoadFile(string filename, int fileStartX, int fileStartY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight); - ITerrainChannel LoadStream(Stream stream); - void SaveFile(string filename, ITerrainChannel map); - void SaveStream(Stream stream, ITerrainChannel map); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs deleted file mode 100644 index 91bc31f..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainModule.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -using System.IO; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Region.Environment.Modules.World.Terrain -{ - public interface ITerrainModule - { - void LoadFromFile(string filename); - void SaveToFile(string filename); - void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action, UUID agentId); - - /// - /// Load a terrain from a stream. - /// - /// - /// Only required here to identify the image type. Not otherwise used in the loading itself. - /// - /// - void LoadFromStream(string filename, Stream stream); - - /// - /// Save a terrain to a stream. - /// - /// - /// Only required here to identify the image type. Not otherwise used in the saving itself. - /// - /// - void SaveToStream(string filename, Stream stream); - - void InstallPlugin(string name, ITerrainEffect plug); - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs b/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs deleted file mode 100644 index 7461560..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/ITerrainPaintableEffect.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain -{ - public interface ITerrainPaintableEffect - { - void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z, double strength, double duration); - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs deleted file mode 100644 index 4d694cc..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/ErodeSphere.cs +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - /// - /// Hydraulic Erosion Brush - /// - public class ErodeSphere : ITerrainPaintableEffect - { - private const double rainHeight = 0.2; - private const int rounds = 10; - private const NeighbourSystem type = NeighbourSystem.Moore; - private const double waterSaturation = 0.30; - - #region Supporting Functions - - private static int[] Neighbours(NeighbourSystem neighbourType, int index) - { - int[] coord = new int[2]; - - index++; - - switch (neighbourType) - { - case NeighbourSystem.Moore: - switch (index) - { - case 1: - coord[0] = -1; - coord[1] = -1; - break; - - case 2: - coord[0] = -0; - coord[1] = -1; - break; - - case 3: - coord[0] = +1; - coord[1] = -1; - break; - - case 4: - coord[0] = -1; - coord[1] = -0; - break; - - case 5: - coord[0] = -0; - coord[1] = -0; - break; - - case 6: - coord[0] = +1; - coord[1] = -0; - break; - - case 7: - coord[0] = -1; - coord[1] = +1; - break; - - case 8: - coord[0] = -0; - coord[1] = +1; - break; - - case 9: - coord[0] = +1; - coord[1] = +1; - break; - - default: - break; - } - break; - - case NeighbourSystem.VonNeumann: - switch (index) - { - case 1: - coord[0] = 0; - coord[1] = -1; - break; - - case 2: - coord[0] = -1; - coord[1] = 0; - break; - - case 3: - coord[0] = +1; - coord[1] = 0; - break; - - case 4: - coord[0] = 0; - coord[1] = +1; - break; - - case 5: - coord[0] = -0; - coord[1] = -0; - break; - - default: - break; - } - break; - } - - return coord; - } - - private enum NeighbourSystem - { - Moore, - VonNeumann - } ; - - #endregion - - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - // Using one 'rain' round for this, so skipping a useless loop - // Will need to adapt back in for the Flood brush - - ITerrainChannel water = new TerrainChannel(map.Width, map.Height); - ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height); - - // Fill with rain - for (x = 0; x < water.Width; x++) - for (y = 0; y < water.Height; y++) - water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration); - - for (int i = 0; i < rounds; i++) - { - // Erode underlying terrain - for (x = 0; x < water.Width; x++) - { - for (y = 0; y < water.Height; y++) - { - if (mask[x,y]) - { - const double solConst = (1.0 / rounds); - double sedDelta = water[x, y] * solConst; - map[x, y] -= sedDelta; - sediment[x, y] += sedDelta; - } - } - } - - // Move water - for (x = 0; x < water.Width; x++) - { - for (y = 0; y < water.Height; y++) - { - if (water[x, y] <= 0) - continue; - - // Step 1. Calculate average of neighbours - - int neighbours = 0; - double altitudeTotal = 0.0; - double altitudeMe = map[x, y] + water[x, y]; - - const int NEIGHBOUR_ME = 4; - const int NEIGHBOUR_MAX = 9; - - for (int j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - int[] coords = Neighbours(type, j); - - coords[0] += x; - coords[1] += y; - - if (coords[0] > map.Width - 1) - continue; - if (coords[1] > map.Height - 1) - continue; - if (coords[0] < 0) - continue; - if (coords[1] < 0) - continue; - - // Calculate total height of this neighbour - double altitudeNeighbour = water[coords[0], coords[1]] + map[coords[0], coords[1]]; - - // If it's greater than me... - if (altitudeNeighbour - altitudeMe < 0) - { - // Add it to our calculations - neighbours++; - altitudeTotal += altitudeNeighbour; - } - } - } - - if (neighbours == 0) - continue; - - double altitudeAvg = altitudeTotal / neighbours; - - // Step 2. Allocate water to neighbours. - for (int j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - int[] coords = Neighbours(type, j); - - coords[0] += x; - coords[1] += y; - - if (coords[0] > map.Width - 1) - continue; - if (coords[1] > map.Height - 1) - continue; - if (coords[0] < 0) - continue; - if (coords[1] < 0) - continue; - - // Skip if we dont have water to begin with. - if (water[x, y] < 0) - continue; - - // Calculate our delta average - double altitudeDelta = altitudeMe - altitudeAvg; - - if (altitudeDelta < 0) - continue; - - // Calculate how much water we can move - double waterMin = Math.Min(water[x, y], altitudeDelta); - double waterDelta = waterMin * ((water[coords[0], coords[1]] + map[coords[0], coords[1]]) - / altitudeTotal); - - double sedimentDelta = sediment[x, y] * (waterDelta / water[x, y]); - - if (sedimentDelta > 0) - { - sediment[x, y] -= sedimentDelta; - sediment[coords[0], coords[1]] += sedimentDelta; - } - } - } - } - } - - // Evaporate - - for (x = 0; x < water.Width; x++) - { - for (y = 0; y < water.Height; y++) - { - water[x, y] *= 1.0 - (rainHeight / rounds); - - double waterCapacity = waterSaturation * water[x, y]; - - double sedimentDeposit = sediment[x, y] - waterCapacity; - if (sedimentDeposit > 0) - { - if (mask[x,y]) - { - sediment[x, y] -= sedimentDeposit; - map[x, y] += sedimentDeposit; - } - } - } - } - } - - // Deposit any remainder (should be minimal) - for (x = 0; x < water.Width; x++) - for (y = 0; y < water.Height; y++) - if (mask[x,y] && sediment[x, y] > 0) - map[x, y] += sediment[x, y]; - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs deleted file mode 100644 index 91c030d..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/FlattenSphere.cs +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - public class FlattenSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - - if (rz < 0) { - double sum = 0.0; - double step2 = 0.0; - duration = 0.009; //MCP Should be read from ini file - - - // compute delta map - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); - - if (z > 0) // add in non-zero amount - { - sum += map[x, y] * z; - step2 += z; - } - } - } - rz = sum / step2; - } - - - // blend in map - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - if (!mask[x,y]) - continue; - - double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * duration; - - if (z > 0) // add in non-zero amount - { - if (z > 1.0) - z = 1.0; - - map[x, y] = (map[x, y] * (1.0 - z)) + (rz * z); - } - - double delta = rz - map[x, y]; - if (Math.Abs(delta) > 0.1) - delta *= 0.25; - - if (delta != 0) // add in non-zero amount - { - map[x, y] += delta; - } - - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs deleted file mode 100644 index d391e94..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/LowerSphere.cs +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - public class LowerSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - int s = (int) (Math.Pow(2, strength) + 0.5); - - int x; - int xFrom = (int)(rx-s+0.5); - int xTo = (int)(rx+s+0.5) + 1; - int yFrom = (int)(ry-s+0.5); - int yTo = (int)(ry+s+0.5) + 1; - - if (xFrom < 0) - xFrom = 0; - - if (yFrom < 0) - yFrom = 0; - - if (xTo > map.Width) - xTo = map.Width; - - if (yTo > map.Width) - yTo = map.Width; - - for (x = xFrom; x < xTo; x++) - { - int y; - for (y = yFrom; y < yTo; y++) - { - if (!mask[x,y]) - continue; - - // Calculate a cos-sphere and add it to the heighmap - double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry))); - double z = Math.Cos(r * Math.PI / (s * 2)); - if (z > 0.0) - { - double newz = map[x, y] - z * duration; - if (newz < 0.0) - map[x, y] = 0.0; - else - map[x, y] = newz; - } - } - } - - } - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs deleted file mode 100644 index 32a6869..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/NoiseSphere.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - public class NoiseSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x; - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (!mask[x,y]) - continue; - - // Calculate a sphere and add it to the heighmap - double z = strength; - z *= z; - z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry)); - - double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0); - - if (z > 0.0) - map[x, y] += noise * z * duration; - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs deleted file mode 100644 index 86d01d3..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/OlsenSphere.cs +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - /// - /// Speed-Optimised Hybrid Erosion Brush - /// - /// As per Jacob Olsen's Paper - /// http://www.oddlabs.com/download/terrain_generation.pdf - /// - public class OlsenSphere : ITerrainPaintableEffect - { - private const double nConst = 1024.0; - private const NeighbourSystem type = NeighbourSystem.Moore; - - #region Supporting Functions - - private static int[] Neighbours(NeighbourSystem neighbourType, int index) - { - int[] coord = new int[2]; - - index++; - - switch (neighbourType) - { - case NeighbourSystem.Moore: - switch (index) - { - case 1: - coord[0] = -1; - coord[1] = -1; - break; - - case 2: - coord[0] = -0; - coord[1] = -1; - break; - - case 3: - coord[0] = +1; - coord[1] = -1; - break; - - case 4: - coord[0] = -1; - coord[1] = -0; - break; - - case 5: - coord[0] = -0; - coord[1] = -0; - break; - - case 6: - coord[0] = +1; - coord[1] = -0; - break; - - case 7: - coord[0] = -1; - coord[1] = +1; - break; - - case 8: - coord[0] = -0; - coord[1] = +1; - break; - - case 9: - coord[0] = +1; - coord[1] = +1; - break; - - default: - break; - } - break; - - case NeighbourSystem.VonNeumann: - switch (index) - { - case 1: - coord[0] = 0; - coord[1] = -1; - break; - - case 2: - coord[0] = -1; - coord[1] = 0; - break; - - case 3: - coord[0] = +1; - coord[1] = 0; - break; - - case 4: - coord[0] = 0; - coord[1] = +1; - break; - - case 5: - coord[0] = -0; - coord[1] = -0; - break; - - default: - break; - } - break; - } - - return coord; - } - - private enum NeighbourSystem - { - Moore, - VonNeumann - } ; - - #endregion - - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x; - - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (!mask[x,y]) - continue; - - double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); - - if (z > 0) // add in non-zero amount - { - const int NEIGHBOUR_ME = 4; - const int NEIGHBOUR_MAX = 9; - - double max = Double.MinValue; - int loc = 0; - - - for (int j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - int[] coords = Neighbours(type, j); - - coords[0] += x; - coords[1] += y; - - if (coords[0] > map.Width - 1) - continue; - if (coords[1] > map.Height - 1) - continue; - if (coords[0] < 0) - continue; - if (coords[1] < 0) - continue; - - double cellmax = map[x, y] - map[coords[0], coords[1]]; - if (cellmax > max) - { - max = cellmax; - loc = j; - } - } - } - - double T = nConst / ((map.Width + map.Height) / 2.0); - // Apply results - if (0 < max && max <= T) - { - int[] maxCoords = Neighbours(type, loc); - double heightDelta = 0.5 * max * z * duration; - map[x, y] -= heightDelta; - map[x + maxCoords[0], y + maxCoords[1]] += heightDelta; - } - } - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs deleted file mode 100644 index a0ff262..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RaiseSphere.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - public class RaiseSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - int s = (int) (Math.Pow(2, strength) + 0.5); - - int x; - int xFrom = (int)(rx-s+0.5); - int xTo = (int)(rx+s+0.5) + 1; - int yFrom = (int)(ry-s+0.5); - int yTo = (int)(ry+s+0.5) + 1; - - if (xFrom < 0) - xFrom = 0; - - if (yFrom < 0) - yFrom = 0; - - if (xTo > map.Width) - xTo = map.Width; - - if (yTo > map.Width) - yTo = map.Width; - - for (x = xFrom; x < xTo; x++) - { - int y; - for (y = yFrom; y < yTo; y++) - { - if (!mask[x,y]) - continue; - - // Calculate a cos-sphere and add it to the heighmap - double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry))); - double z = Math.Cos(r * Math.PI / (s * 2)); - if (z > 0.0) - map[x, y] += z * duration; - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs deleted file mode 100644 index af6d94d..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/RevertSphere.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - public class RevertSphere : ITerrainPaintableEffect - { - private readonly ITerrainChannel m_revertmap; - - public RevertSphere(ITerrainChannel revertmap) - { - m_revertmap = revertmap; - } - - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - duration = 0.03; //MCP Should be read from ini file - - if (duration > 1.0) - duration = 1.0; - if (duration < 0) - return; - - int x; - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (!mask[x,y]) - continue; - - // Calculate a sphere and add it to the heighmap - double z = strength; - z *= z; - z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry)); - - if (z > 0.0) - { - z *= duration; - map[x, y] = (map[x, y] * (1.0 - z)) + (m_revertmap[x, y] * z); - } - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs deleted file mode 100644 index fe270f7..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/SmoothSphere.cs +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - public class SmoothSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - double[,] tweak = new double[map.Width,map.Height]; - - double area = strength; - double step = strength / 4.0; - duration = 0.03; //MCP Should be read from ini file - - - // compute delta map - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); - - if (z > 0) // add in non-zero amount - { - double average = 0.0; - int avgsteps = 0; - - double n; - for (n = 0.0 - area; n < area; n += step) - { - double l; - for (l = 0.0 - area; l < area; l += step) - { - avgsteps++; - average += TerrainUtil.GetBilinearInterpolate(x + n, y + l, map); - } - } - tweak[x, y] = average / avgsteps; - } - } - } - // blend in map - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - if (!mask[x,y]) - continue; - - double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); - - if (z > 0) // add in non-zero amount - { - double da = z; - double a = (map[x, y] - tweak[x, y]) * da; - double newz = map[x, y] - (a * duration); - - if (newz > 0.0) - map[x, y] = newz; - } - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs b/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs deleted file mode 100644 index faba119..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/PaintBrushes/WeatherSphere.cs +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes -{ - /// - /// Thermal Weathering Paint Brush - /// - public class WeatherSphere : ITerrainPaintableEffect - { - private const double talus = 0.2; - private const NeighbourSystem type = NeighbourSystem.Moore; - - #region Supporting Functions - - private static int[] Neighbours(NeighbourSystem neighbourType, int index) - { - int[] coord = new int[2]; - - index++; - - switch (neighbourType) - { - case NeighbourSystem.Moore: - switch (index) - { - case 1: - coord[0] = -1; - coord[1] = -1; - break; - - case 2: - coord[0] = -0; - coord[1] = -1; - break; - - case 3: - coord[0] = +1; - coord[1] = -1; - break; - - case 4: - coord[0] = -1; - coord[1] = -0; - break; - - case 5: - coord[0] = -0; - coord[1] = -0; - break; - - case 6: - coord[0] = +1; - coord[1] = -0; - break; - - case 7: - coord[0] = -1; - coord[1] = +1; - break; - - case 8: - coord[0] = -0; - coord[1] = +1; - break; - - case 9: - coord[0] = +1; - coord[1] = +1; - break; - - default: - break; - } - break; - - case NeighbourSystem.VonNeumann: - switch (index) - { - case 1: - coord[0] = 0; - coord[1] = -1; - break; - - case 2: - coord[0] = -1; - coord[1] = 0; - break; - - case 3: - coord[0] = +1; - coord[1] = 0; - break; - - case 4: - coord[0] = 0; - coord[1] = +1; - break; - - case 5: - coord[0] = -0; - coord[1] = -0; - break; - - default: - break; - } - break; - } - - return coord; - } - - private enum NeighbourSystem - { - Moore, - VonNeumann - } ; - - #endregion - - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x; - - for (x = 0; x < map.Width; x++) - { - int y; - for (y = 0; y < map.Height; y++) - { - if (!mask[x,y]) - continue; - - double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); - - if (z > 0) // add in non-zero amount - { - const int NEIGHBOUR_ME = 4; - const int NEIGHBOUR_MAX = 9; - - for (int j = 0; j < NEIGHBOUR_MAX; j++) - { - if (j != NEIGHBOUR_ME) - { - int[] coords = Neighbours(type, j); - - coords[0] += x; - coords[1] += y; - - if (coords[0] > map.Width - 1) - continue; - if (coords[1] > map.Height - 1) - continue; - if (coords[0] < 0) - continue; - if (coords[1] < 0) - continue; - - double heightF = map[x, y]; - double target = map[coords[0], coords[1]]; - - if (target > heightF + talus) - { - double calc = duration * ((target - heightF) - talus) * z; - heightF += calc; - target -= calc; - } - - map[x, y] = heightF; - map[coords[0], coords[1]] = target; - } - } - } - } - } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs b/OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs deleted file mode 100644 index 2411de0..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainException.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; - -namespace OpenSim.Region.Environment.Modules.World.Terrain -{ - public class TerrainException : Exception - { - public TerrainException() - { - } - - public TerrainException(string msg) : base(msg) - { - } - - public TerrainException(string msg, Exception e) : base(msg, e) - { - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs b/OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs deleted file mode 100644 index bc601dc..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/TerrainModule.cs +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.Framework.InterfaceCommander; -using OpenSim.Region.Environment.Modules.World.Terrain.FileLoaders; -using OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes; -using OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain -{ - public class TerrainModule : IRegionModule, ICommandableModule, ITerrainModule - { - #region StandardTerrainEffects enum - - /// - /// A standard set of terrain brushes and effects recognised by viewers - /// - public enum StandardTerrainEffects : byte - { - Flatten = 0, - Raise = 1, - Lower = 2, - Smooth = 3, - Noise = 4, - Revert = 5, - - // Extended brushes - Erode = 255, - Weather = 254, - Olsen = 253 - } - - #endregion - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private readonly Commander m_commander = new Commander("terrain"); - - private readonly Dictionary m_floodeffects = - new Dictionary(); - - private readonly Dictionary m_loaders = new Dictionary(); - - private readonly Dictionary m_painteffects = - new Dictionary(); - - private ITerrainChannel m_channel; - private Dictionary m_plugineffects; - private ITerrainChannel m_revert; - private Scene m_scene; - private bool m_tainted; - - #region ICommandableModule Members - - public ICommander CommandInterface - { - get { return m_commander; } - } - - #endregion - - #region IRegionModule Members - - /// - /// Creates and initialises a terrain module for a region - /// - /// Region initialising - /// Config for the region - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - - // Install terrain module in the simulator - if (m_scene.Heightmap == null) - { - lock (m_scene) - { - m_channel = new TerrainChannel(); - m_scene.Heightmap = m_channel; - m_revert = new TerrainChannel(); - UpdateRevertMap(); - } - } - else - { - m_channel = m_scene.Heightmap; - m_revert = new TerrainChannel(); - UpdateRevertMap(); - } - - m_scene.RegisterModuleInterface(this); - m_scene.EventManager.OnNewClient += EventManager_OnNewClient; - m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; - m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; - } - - /// - /// Enables terrain module when called - /// - public void PostInitialise() - { - InstallDefaultEffects(); - InstallInterfaces(); - LoadPlugins(); - } - - public void Close() - { - } - - public string Name - { - get { return "TerrainModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region ITerrainModule Members - - /// - /// Loads a terrain file from disk and installs it in the scene. - /// - /// Filename to terrain file. Type is determined by extension. - public void LoadFromFile(string filename) - { - foreach (KeyValuePair loader in m_loaders) - { - if (filename.EndsWith(loader.Key)) - { - lock (m_scene) - { - try - { - ITerrainChannel channel = loader.Value.LoadFile(filename); - if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize) - { - // TerrainChannel expects a RegionSize x RegionSize map, currently - throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}", - Constants.RegionSize, Constants.RegionSize)); - } - m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); - m_scene.Heightmap = channel; - m_channel = channel; - UpdateRevertMap(); - } - catch (NotImplementedException) - { - m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + - " parser does not support file loading. (May be save only)"); - throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); - } - catch (FileNotFoundException) - { - m_log.Error( - "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); - throw new TerrainException( - String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); - } - catch (ArgumentException e) - { - m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); - throw new TerrainException( - String.Format("Unable to load heightmap: {0}", e.Message)); - } - } - CheckForTerrainUpdates(); - m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); - return; - } - } - - m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format."); - throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); - } - - /// - /// Saves the current heightmap to a specified file. - /// - /// The destination filename - public void SaveToFile(string filename) - { - try - { - foreach (KeyValuePair loader in m_loaders) - { - if (filename.EndsWith(loader.Key)) - { - loader.Value.SaveFile(filename, m_channel); - return; - } - } - } - catch (NotImplementedException) - { - m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); - throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); - } - } - - /// - /// Loads a terrain file from a stream and installs it in the scene. - /// - /// Filename to terrain file. Type is determined by extension. - /// - public void LoadFromStream(string filename, Stream stream) - { - foreach (KeyValuePair loader in m_loaders) - { - if (@filename.EndsWith(loader.Key)) - { - lock (m_scene) - { - try - { - ITerrainChannel channel = loader.Value.LoadStream(stream); - m_scene.Heightmap = channel; - m_channel = channel; - UpdateRevertMap(); - } - catch (NotImplementedException) - { - m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + - " parser does not support file loading. (May be save only)"); - throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); - } - } - - CheckForTerrainUpdates(); - m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); - return; - } - } - m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader available for that format."); - throw new TerrainException(String.Format("unable to load heightmap from file {0}: no loader available for that format", filename)); - } - - /// - /// Modify Land - /// - /// Land-position (X,Y,0) - /// The size of the brush (0=small, 1=medium, 2=large) - /// 0=LAND_LEVEL, 1=LAND_RAISE, 2=LAND_LOWER, 3=LAND_SMOOTH, 4=LAND_NOISE, 5=LAND_REVERT - /// UUID of script-owner - public void ModifyTerrain(UUID user, Vector3 pos, byte size, byte action, UUID agentId) - { - client_OnModifyTerrain(user, (float)pos.Z, (float)0.25, size, action, pos.Y, pos.X, pos.Y, pos.X, agentId); - } - - /// - /// Saves the current heightmap to a specified stream. - /// - /// The destination filename. Used here only to identify the image type - /// - public void SaveToStream(string filename, Stream stream) - { - try - { - foreach (KeyValuePair loader in m_loaders) - { - if (filename.EndsWith(loader.Key)) - { - loader.Value.SaveStream(stream, m_channel); - return; - } - } - } - catch (NotImplementedException) - { - m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); - throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); - } - } - - #region Plugin Loading Methods - - private void LoadPlugins() - { - m_plugineffects = new Dictionary(); - // Load the files in the Terrain/ dir - string[] files = Directory.GetFiles("Terrain"); - foreach (string file in files) - { - m_log.Info("Loading effects in " + file); - try - { - Assembly library = Assembly.LoadFrom(file); - foreach (Type pluginType in library.GetTypes()) - { - try - { - if (pluginType.IsAbstract || pluginType.IsNotPublic) - continue; - - string typeName = pluginType.Name; - - if (pluginType.GetInterface("ITerrainEffect", false) != null) - { - ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); - - InstallPlugin(typeName, terEffect); - } - else if (pluginType.GetInterface("ITerrainLoader", false) != null) - { - ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); - m_loaders[terLoader.FileExtension] = terLoader; - m_log.Info("L ... " + typeName); - } - } - catch (AmbiguousMatchException) - { - } - } - } - catch (BadImageFormatException) - { - } - } - } - - public void InstallPlugin(string pluginName, ITerrainEffect effect) - { - lock (m_plugineffects) - { - if (!m_plugineffects.ContainsKey(pluginName)) - { - m_plugineffects.Add(pluginName, effect); - m_log.Info("E ... " + pluginName); - } - else - { - m_plugineffects[pluginName] = effect; - m_log.Warn("E ... " + pluginName + " (Replaced)"); - } - } - } - - #endregion - - #endregion - - /// - /// Installs into terrain module the standard suite of brushes - /// - private void InstallDefaultEffects() - { - // Draggable Paint Brush Effects - m_painteffects[StandardTerrainEffects.Raise] = new RaiseSphere(); - m_painteffects[StandardTerrainEffects.Lower] = new LowerSphere(); - m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere(); - m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere(); - m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere(); - m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert); - m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere(); - m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere(); - m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere(); - - // Area of effect selection effects - m_floodeffects[StandardTerrainEffects.Raise] = new RaiseArea(); - m_floodeffects[StandardTerrainEffects.Lower] = new LowerArea(); - m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea(); - m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea(); - m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); - m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); - - // Filesystem load/save loaders - m_loaders[".r32"] = new RAW32(); - m_loaders[".f32"] = m_loaders[".r32"]; - m_loaders[".ter"] = new Terragen(); - m_loaders[".raw"] = new LLRAW(); - m_loaders[".jpg"] = new JPEG(); - m_loaders[".jpeg"] = m_loaders[".jpg"]; - m_loaders[".bmp"] = new BMP(); - m_loaders[".png"] = new PNG(); - m_loaders[".gif"] = new GIF(); - m_loaders[".tif"] = new TIFF(); - m_loaders[".tiff"] = m_loaders[".tif"]; - } - - /// - /// Saves the current state of the region into the revert map buffer. - /// - public void UpdateRevertMap() - { - int x; - for (x = 0; x < m_channel.Width; x++) - { - int y; - for (y = 0; y < m_channel.Height; y++) - { - m_revert[x, y] = m_channel[x, y]; - } - } - } - - /// - /// Loads a tile from a larger terrain file and installs it into the region. - /// - /// The terrain file to load - /// The width of the file in units - /// The height of the file in units - /// Where to begin our slice - /// Where to begin our slice - public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) - { - int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX; - int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY; - - if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) - { - // this region is included in the tile request - foreach (KeyValuePair loader in m_loaders) - { - if (filename.EndsWith(loader.Key)) - { - lock (m_scene) - { - ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, - fileWidth, fileHeight, - (int) Constants.RegionSize, - (int) Constants.RegionSize); - m_scene.Heightmap = channel; - m_channel = channel; - UpdateRevertMap(); - } - return; - } - } - } - } - - /// - /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections - /// - private void EventManager_OnTerrainTick() - { - if (m_tainted) - { - m_tainted = false; - m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); - m_scene.SaveTerrain(); - - // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. - //m_scene.CreateTerrainTexture(true); - } - } - - /// - /// Processes commandline input. Do not call directly. - /// - /// Commandline arguments - private void EventManager_OnPluginConsole(string[] args) - { - if (args[0] == "terrain") - { - if (args.Length == 1) - { - m_commander.ProcessConsoleCommand("help", new string[0]); - return; - } - - string[] tmpArgs = new string[args.Length - 2]; - int i; - for (i = 2; i < args.Length; i++) - tmpArgs[i - 2] = args[i]; - - m_commander.ProcessConsoleCommand(args[1], tmpArgs); - } - } - - /// - /// Installs terrain brush hook to IClientAPI - /// - /// - private void EventManager_OnNewClient(IClientAPI client) - { - client.OnModifyTerrain += client_OnModifyTerrain; - client.OnBakeTerrain += client_OnBakeTerrain; - } - - /// - /// Checks to see if the terrain has been modified since last check - /// but won't attempt to limit those changes to the limits specified in the estate settings - /// currently invoked by the command line operations in the region server only - /// - private void CheckForTerrainUpdates() - { - CheckForTerrainUpdates(false); - } - - /// - /// Checks to see if the terrain has been modified since last check. - /// If it has been modified, every all the terrain patches are sent to the client. - /// If the call is asked to respect the estate settings for terrain_raise_limit and - /// terrain_lower_limit, it will clamp terrain updates between these values - /// currently invoked by client_OnModifyTerrain only and not the Commander interfaces - /// should height map deltas be limited to the estate settings limits - /// - private void CheckForTerrainUpdates(bool respectEstateSettings) - { - bool shouldTaint = false; - float[] serialised = m_channel.GetFloatsSerialised(); - int x; - for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) - { - int y; - for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize) - { - if (m_channel.Tainted(x, y)) - { - // if we should respect the estate settings then - // fixup and height deltas that don't respect them - if (respectEstateSettings && LimitChannelChanges(x, y)) - { - // this has been vetoed, so update - // what we are going to send to the client - serialised = m_channel.GetFloatsSerialised(); - } - - SendToClients(serialised, x, y); - shouldTaint = true; - } - } - } - if (shouldTaint) - { - m_tainted = true; - } - } - - /// - /// Checks to see height deltas in the tainted terrain patch at xStart ,yStart - /// are all within the current estate limits - /// true if changes were limited, false otherwise - /// - private bool LimitChannelChanges(int xStart, int yStart) - { - bool changesLimited = false; - double minDelta = m_scene.RegionInfo.RegionSettings.TerrainLowerLimit; - double maxDelta = m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; - - // loop through the height map for this patch and compare it against - // the revert map - for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) - { - for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) - { - - double requestedHeight = m_channel[x, y]; - double bakedHeight = m_revert[x, y]; - double requestedDelta = requestedHeight - bakedHeight; - - if (requestedDelta > maxDelta) - { - m_channel[x, y] = bakedHeight + maxDelta; - changesLimited = true; - } - else if (requestedDelta < minDelta) - { - m_channel[x, y] = bakedHeight + minDelta; //as lower is a -ve delta - changesLimited = true; - } - } - } - - return changesLimited; - } - - /// - /// Sends a copy of the current terrain to the scenes clients - /// - /// A copy of the terrain as a 1D float array of size w*h - /// The patch corner to send - /// The patch corner to send - private void SendToClients(float[] serialised, int x, int y) - { - m_scene.ForEachClient( - delegate(IClientAPI controller) - { controller.SendLayerData( - x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised); - } - ); - } - - private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action, - float north, float west, float south, float east, UUID agentId) - { - bool god = m_scene.Permissions.IsGod(user); - bool allowed = false; - if (north == south && east == west) - { - if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) - { - bool[,] allowMask = new bool[m_channel.Width,m_channel.Height]; - allowMask.Initialize(); - int n = size + 1; - if (n > 2) - n = 4; - - int zx = (int) (west + 0.5); - int zy = (int) (north + 0.5); - - int dx; - for (dx=-n; dx<=n; dx++) - { - int dy; - for (dy=-n; dy<=n; dy++) - { - int x = zx + dx; - int y = zy + dy; - if (x>=0 && y>=0 && x west) - { - if (y < north && y > south) - { - if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) - { - fillArea[x, y] = true; - allowed = true; - } - } - } - } - } - - if (allowed) - { - m_floodeffects[(StandardTerrainEffects) action].FloodEffect( - m_channel, fillArea, size); - - CheckForTerrainUpdates(!god); //revert changes outside estate limits - } - } - else - { - m_log.Debug("Unknown terrain flood type " + action); - } - } - } - - private void client_OnBakeTerrain(IClientAPI remoteClient) - { - // Not a good permissions check (see client_OnModifyTerrain above), need to check the entire area. - // for now check a point in the centre of the region - - if (m_scene.Permissions.CanIssueEstateCommand(remoteClient.AgentId, true)) - { - InterfaceBakeTerrain(null); //bake terrain does not use the passed in parameter - } - } - - #region Console Commands - - private void InterfaceLoadFile(Object[] args) - { - LoadFromFile((string) args[0]); - CheckForTerrainUpdates(); - } - - private void InterfaceLoadTileFile(Object[] args) - { - LoadFromFile((string) args[0], - (int) args[1], - (int) args[2], - (int) args[3], - (int) args[4]); - CheckForTerrainUpdates(); - } - - private void InterfaceSaveFile(Object[] args) - { - SaveToFile((string) args[0]); - } - - private void InterfaceBakeTerrain(Object[] args) - { - UpdateRevertMap(); - } - - private void InterfaceRevertTerrain(Object[] args) - { - int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] = m_revert[x, y]; - - CheckForTerrainUpdates(); - } - - private void InterfaceFlipTerrain(Object[] args) - { - String direction = (String)args[0]; - - if (direction.ToLower().StartsWith("y")) - { - for (int x = 0; x < Constants.RegionSize; x++) - { - for (int y = 0; y < Constants.RegionSize / 2; y++) - { - double height = m_channel[x, y]; - double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y]; - m_channel[x, y] = flippedHeight; - m_channel[x, (int)Constants.RegionSize - 1 - y] = height; - - } - } - } - else if (direction.ToLower().StartsWith("x")) - { - for (int y = 0; y < Constants.RegionSize; y++) - { - for (int x = 0; x < Constants.RegionSize / 2; x++) - { - double height = m_channel[x, y]; - double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y]; - m_channel[x, y] = flippedHeight; - m_channel[(int)Constants.RegionSize - 1 - x, y] = height; - - } - } - } - else - { - m_log.Error("Unrecognised direction - need x or y"); - } - - - CheckForTerrainUpdates(); - } - - private void InterfaceElevateTerrain(Object[] args) - { - int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] += (double) args[0]; - CheckForTerrainUpdates(); - } - - private void InterfaceMultiplyTerrain(Object[] args) - { - int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] *= (double) args[0]; - CheckForTerrainUpdates(); - } - - private void InterfaceLowerTerrain(Object[] args) - { - int x, y; - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] -= (double) args[0]; - CheckForTerrainUpdates(); - } - - private void InterfaceFillTerrain(Object[] args) - { - int x, y; - - for (x = 0; x < m_channel.Width; x++) - for (y = 0; y < m_channel.Height; y++) - m_channel[x, y] = (double) args[0]; - CheckForTerrainUpdates(); - } - - private void InterfaceShowDebugStats(Object[] args) - { - double max = Double.MinValue; - double min = double.MaxValue; - double sum = 0; - - int x; - for (x = 0; x < m_channel.Width; x++) - { - int y; - for (y = 0; y < m_channel.Height; y++) - { - sum += m_channel[x, y]; - if (max < m_channel[x, y]) - max = m_channel[x, y]; - if (min > m_channel[x, y]) - min = m_channel[x, y]; - } - } - - double avg = sum / (m_channel.Height * m_channel.Width); - - m_log.Info("Channel " + m_channel.Width + "x" + m_channel.Height); - m_log.Info("max/min/avg/sum: " + max + "/" + min + "/" + avg + "/" + sum); - } - - private void InterfaceEnableExperimentalBrushes(Object[] args) - { - if ((bool) args[0]) - { - m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); - m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); - m_painteffects[StandardTerrainEffects.Smooth] = new ErodeSphere(); - } - else - { - InstallDefaultEffects(); - } - } - - private void InterfaceRunPluginEffect(Object[] args) - { - if ((string) args[0] == "list") - { - m_log.Info("List of loaded plugins"); - foreach (KeyValuePair kvp in m_plugineffects) - { - m_log.Info(kvp.Key); - } - return; - } - if ((string) args[0] == "reload") - { - LoadPlugins(); - return; - } - if (m_plugineffects.ContainsKey((string) args[0])) - { - m_plugineffects[(string) args[0]].RunEffect(m_channel); - CheckForTerrainUpdates(); - } - else - { - m_log.Warn("No such plugin effect loaded."); - } - } - - private void InstallInterfaces() - { - // Load / Save - string supportedFileExtensions = ""; - foreach (KeyValuePair loader in m_loaders) - supportedFileExtensions += " " + loader.Key + " (" + loader.Value + ")"; - - Command loadFromFileCommand = - new Command("load", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadFile, "Loads a terrain from a specified file."); - loadFromFileCommand.AddArgument("filename", - "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + - supportedFileExtensions, "String"); - - Command saveToFileCommand = - new Command("save", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveFile, "Saves the current heightmap to a specified file."); - saveToFileCommand.AddArgument("filename", - "The destination filename for your heightmap, the file extension determines the format to save in. Supported extensions include: " + - supportedFileExtensions, "String"); - - Command loadFromTileCommand = - new Command("load-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadTileFile, "Loads a terrain from a section of a larger file."); - loadFromTileCommand.AddArgument("filename", - "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " + - supportedFileExtensions, "String"); - loadFromTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer"); - loadFromTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer"); - loadFromTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file", - "Integer"); - loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file", - "Integer"); - - // Terrain adjustments - Command fillRegionCommand = - new Command("fill", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFillTerrain, "Fills the current heightmap with a specified value."); - fillRegionCommand.AddArgument("value", "The numeric value of the height you wish to set your region to.", - "Double"); - - Command elevateCommand = - new Command("elevate", CommandIntentions.COMMAND_HAZARDOUS, InterfaceElevateTerrain, "Raises the current heightmap by the specified amount."); - elevateCommand.AddArgument("amount", "The amount of height to add to the terrain in meters.", "Double"); - - Command lowerCommand = - new Command("lower", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLowerTerrain, "Lowers the current heightmap by the specified amount."); - lowerCommand.AddArgument("amount", "The amount of height to remove from the terrain in meters.", "Double"); - - Command multiplyCommand = - new Command("multiply", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified."); - multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); - - Command bakeRegionCommand = - new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); - Command revertRegionCommand = - new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); - - Command flipCommand = - new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis"); - flipCommand.AddArgument("direction", "[x|y] the direction to flip the terrain in", "String"); - - // Debug - Command showDebugStatsCommand = - new Command("stats", CommandIntentions.COMMAND_STATISTICAL, InterfaceShowDebugStats, - "Shows some information about the regions heightmap for debugging purposes."); - - Command experimentalBrushesCommand = - new Command("newbrushes", CommandIntentions.COMMAND_HAZARDOUS, InterfaceEnableExperimentalBrushes, - "Enables experimental brushes which replace the standard terrain brushes. WARNING: This is a debug setting and may be removed at any time."); - experimentalBrushesCommand.AddArgument("Enabled?", "true / false - Enable new brushes", "Boolean"); - - //Plugins - Command pluginRunCommand = - new Command("effect", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRunPluginEffect, "Runs a specified plugin effect"); - pluginRunCommand.AddArgument("name", "The plugin effect you wish to run, or 'list' to see all plugins", "String"); - - m_commander.RegisterCommand("load", loadFromFileCommand); - m_commander.RegisterCommand("load-tile", loadFromTileCommand); - m_commander.RegisterCommand("save", saveToFileCommand); - m_commander.RegisterCommand("fill", fillRegionCommand); - m_commander.RegisterCommand("elevate", elevateCommand); - m_commander.RegisterCommand("lower", lowerCommand); - m_commander.RegisterCommand("multiply", multiplyCommand); - m_commander.RegisterCommand("bake", bakeRegionCommand); - m_commander.RegisterCommand("revert", revertRegionCommand); - m_commander.RegisterCommand("newbrushes", experimentalBrushesCommand); - m_commander.RegisterCommand("stats", showDebugStatsCommand); - m_commander.RegisterCommand("effect", pluginRunCommand); - m_commander.RegisterCommand("flip", flipCommand); - - // Add this to our scene so scripts can call these functions - m_scene.RegisterModuleCommander(m_commander); - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs deleted file mode 100644 index 2acd5bc..0000000 --- a/OpenSim/Region/Environment/Modules/World/Terrain/Tests/TerrainTest.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Terrain.PaintBrushes; - -namespace OpenSim.Region.Environment.Modules.World.Terrain.Tests -{ - [TestFixture] - public class TerrainTest - { - [Test] - public void BrushTest() - { - bool[,] allowMask = new bool[256, 256]; - int x; - int y; - for (x=0; x<128; x++) - { - for (y=0; y<256; y++) - { - allowMask[x,y] = true; - } - } - - // - // Test RaiseSphere - // - TerrainChannel map = new TerrainChannel(256, 256); - ITerrainPaintableEffect effect = new RaiseSphere(); - - effect.PaintEffect(map, allowMask, 128.0, 128.0, -1.0, 2, 0.1); - Assert.That(map[127, 128] > 0.0, "Raise brush should raising value at this point (127,128)."); - Assert.That(map[124, 128] > 0.0, "Raise brush should raising value at this point (124,128)."); - Assert.That(map[123, 128] == 0.0, "Raise brush should not change value at this point (123,128)."); - Assert.That(map[128, 128] == 0.0, "Raise brush should not change value at this point (128,128)."); - Assert.That(map[0, 128] == 0.0, "Raise brush should not change value at this point (0,128)."); - - // - // Test LowerSphere - // - map = new TerrainChannel(256, 256); - for (x=0; x= 0.0, "Lower should not lowering value below 0.0 at this point (127,128)."); - Assert.That(map[127, 128] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128)."); - Assert.That(map[124, 128] < 1.0, "Lower brush should lowering value at this point (124,128)."); - Assert.That(map[123, 128] == 1.0, "Lower brush should not change value at this point (123,128)."); - Assert.That(map[128, 128] == 1.0, "Lower brush should not change value at this point (128,128)."); - Assert.That(map[0, 128] == 1.0, "Lower brush should not change value at this point (0,128)."); - } - - [Test] - public void TerrainChannelTest() - { - TerrainChannel x = new TerrainChannel(256, 256); - Assert.That(x[0, 0] == 0.0, "Terrain not initialising correctly."); - - x[0, 0] = 1.0; - Assert.That(x[0, 0] == 1.0, "Terrain not setting values correctly."); - - x[0, 0] = 0; - x[0, 0] += 5.0; - x[0, 0] -= 1.0; - Assert.That(x[0, 0] == 4.0, "Terrain addition/subtraction error."); - - x[0, 0] = Math.PI; - double[,] doublesExport = x.GetDoubles(); - Assert.That(doublesExport[0, 0] == Math.PI, "Export to double[,] array not working correctly."); - - x[0, 0] = 1.0; - float[] floatsExport = x.GetFloatsSerialised(); - Assert.That(floatsExport[0] == 1.0f, "Export to float[] not working correctly."); - - x[0, 0] = 1.0; - Assert.That(x.Tainted(0, 0), "Terrain channel tainting not working correctly."); - Assert.That(!x.Tainted(0, 0), "Terrain channel tainting not working correctly."); - - TerrainChannel y = x.Copy(); - Assert.That(!ReferenceEquals(x, y), "Terrain copy not duplicating correctly."); - Assert.That(!ReferenceEquals(x.GetDoubles(), y.GetDoubles()), "Terrain array not duplicating correctly."); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs deleted file mode 100644 index 8a49540..0000000 --- a/OpenSim/Region/Environment/Modules/World/TreePopulator/TreePopulatorModule.cs +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Timers; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.TreePopulator -{ - /// - /// Version 2.0 - Very hacky compared to the original. Will fix original and release as 0.3 later. - /// - public class TreePopulatorModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Scene m_scene; - - public double m_tree_density = 50.0; // Aim for this many per region - public double m_tree_updates = 1000.0; // MS between updates - private bool m_active_trees = false; - private List m_trees; - Timer CalculateTrees; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - try - { - m_tree_density = config.Configs["Trees"].GetDouble("tree_density", m_tree_density); - m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees); - } - catch (Exception) - { - } - - m_trees = new List(); - m_scene = scene; - - m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; - - if (m_active_trees) - activeizeTreeze(true); - - m_log.Debug("[TREES]: Initialised tree module"); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "TreePopulatorModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - private void EventManager_OnPluginConsole(string[] args) - { - if (args.Length == 1) - { - if (args[0] == "tree") - { - UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (uuid == UUID.Zero) - uuid = m_scene.RegionInfo.MasterAvatarAssignedUUID; - m_log.Debug("[TREES]: New tree planting"); - CreateTree(uuid, new Vector3(128.0f, 128.0f, 0.0f)); - - } - } - - if (args.Length == 2 || args.Length == 3) - { - if (args[1] == "active") - { - if (args.Length >= 3) - { - if (args[2] == "true" && !m_active_trees) - { - m_active_trees = true; - activeizeTreeze(m_active_trees); - m_log.Info("[TREES]: Activizing Trees"); - } - if (args[2] == "false" && m_active_trees) - { - m_active_trees = false; - activeizeTreeze(m_active_trees); - m_log.Info("[TREES]: Trees no longer Active, for now..."); - } - } - else - { - m_log.Info("[TREES]: When setting the tree module active via the console, you must specify true or false"); - } - } - } - - } - - private void activeizeTreeze(bool activeYN) - { - if (activeYN) - { - CalculateTrees = new Timer(m_tree_updates); - CalculateTrees.Elapsed += CalculateTrees_Elapsed; - CalculateTrees.Start(); - } - else - { - CalculateTrees.Stop(); - } - } - - private void growTrees() - { - foreach (UUID tree in m_trees) - { - if (m_scene.Entities.ContainsKey(tree)) - { - SceneObjectPart s_tree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart; - - // 100 seconds to grow 1m - s_tree.Scale += new Vector3(0.1f, 0.1f, 0.1f); - s_tree.SendFullUpdateToAllClients(); - //s_tree.ScheduleTerseUpdate(); - } - else - { - m_trees.Remove(tree); - } - } - } - - private void seedTrees() - { - foreach (UUID tree in m_trees) - { - if (m_scene.Entities.ContainsKey(tree)) - { - SceneObjectPart s_tree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart; - - if (s_tree.Scale.X > 0.5) - { - if (Util.RandomClass.NextDouble() > 0.75) - { - SpawnChild(s_tree); - } - } - } - else - { - m_trees.Remove(tree); - } - } - } - - private void killTrees() - { - foreach (UUID tree in m_trees) - { - double killLikelyhood = 0.0; - - if (m_scene.Entities.ContainsKey(tree)) - { - SceneObjectPart selectedTree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart; - double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) + - Math.Pow(selectedTree.Scale.Y, 2) + - Math.Pow(selectedTree.Scale.Z, 2)); - - foreach (UUID picktree in m_trees) - { - if (picktree != tree) - { - SceneObjectPart pickedTree = ((SceneObjectGroup) m_scene.Entities[picktree]).RootPart; - - double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) + - Math.Pow(pickedTree.Scale.Y, 2) + - Math.Pow(pickedTree.Scale.Z, 2)); - - double pickedTreeDistance = Math.Sqrt(Math.Pow(Math.Abs(pickedTree.AbsolutePosition.X - selectedTree.AbsolutePosition.X), 2) + - Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Y - selectedTree.AbsolutePosition.Y), 2) + - Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Z - selectedTree.AbsolutePosition.Z), 2)); - - killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1; - } - } - - if (Util.RandomClass.NextDouble() < killLikelyhood) - { - m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); - m_trees.Remove(selectedTree.ParentGroup.UUID); - - m_scene.ForEachClient(delegate(IClientAPI controller) - { - controller.SendKillObject(m_scene.RegionInfo.RegionHandle, - selectedTree.LocalId); - }); - - break; - } - selectedTree.SetText(killLikelyhood.ToString(), new Vector3(1.0f, 1.0f, 1.0f), 1.0); - } - else - { - m_trees.Remove(tree); - } - } - } - - private void SpawnChild(SceneObjectPart s_tree) - { - Vector3 position = new Vector3(); - - position.X = s_tree.AbsolutePosition.X + (1 * (-1 * Util.RandomClass.Next(1))); - if (position.X > 255) - position.X = 255; - if (position.X < 0) - position.X = 0; - position.Y = s_tree.AbsolutePosition.Y + (1 * (-1 * Util.RandomClass.Next(1))); - if (position.Y > 255) - position.Y = 255; - if (position.Y < 0) - position.Y = 0; - - double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); - double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); - - position.X += (float) randX; - position.Y += (float) randY; - - UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (uuid == UUID.Zero) - uuid = m_scene.RegionInfo.MasterAvatarAssignedUUID; - - CreateTree(uuid, position); - } - - private void CreateTree(UUID uuid, Vector3 position) - { - position.Z = (float) m_scene.Heightmap[(int) position.X, (int) position.Y]; - - IVegetationModule module = m_scene.RequestModuleInterface(); - - if (null == module) - return; - - SceneObjectGroup tree - = module.AddTree( - uuid, UUID.Zero, new Vector3(0.1f, 0.1f, 0.1f), Quaternion.Identity, position, Tree.Cypress1, false); - - m_trees.Add(tree.UUID); - tree.SendGroupFullUpdate(); - } - - private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e) - { - growTrees(); - seedTrees(); - killTrees(); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs deleted file mode 100644 index 4c4ca0d..0000000 --- a/OpenSim/Region/Environment/Modules/World/Vegetation/VegetationModule.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Vegetation -{ - public class VegetationModule : IRegionModule, IVegetationModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - - protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree }; - public PCode[] CreationCapabilities { get { return creationCapabilities; } } - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() {} - public void Close() {} - public string Name { get { return "Vegetation Module"; } } - public bool IsSharedModule { get { return false; } } - - public SceneObjectGroup AddTree( - UUID uuid, UUID groupID, Vector3 scale, Quaternion rotation, Vector3 position, Tree treeType, bool newTree) - { - PrimitiveBaseShape treeShape = new PrimitiveBaseShape(); - treeShape.PathCurve = 16; - treeShape.PathEnd = 49900; - treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree; - treeShape.Scale = scale; - treeShape.State = (byte)treeType; - - return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); - } - - public SceneObjectGroup CreateEntity( - UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) - { - if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0) - { - m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); - return null; - } - - SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID); - - // if grass or tree, make phantom - //rootPart.TrimPermissions(); - rootPart.AddFlag(PrimFlags.Phantom); - if (rootPart.Shape.PCode != (byte)PCode.Grass) - AdaptTree(ref shape); - - m_scene.AddNewSceneObject(sceneObject, true); - sceneObject.SetGroup(groupID, null); - - return sceneObject; - } - - protected void AdaptTree(ref PrimitiveBaseShape tree) - { - // Tree size has to be adapted depending on its type - switch ((Tree)tree.State) - { - case Tree.Cypress1: - case Tree.Cypress2: - tree.Scale = new Vector3(4, 4, 10); - break; - - // case... other tree types - // tree.Scale = new Vector3(?, ?, ?); - // break; - - default: - tree.Scale = new Vector3(4, 4, 4); - break; - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs b/OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs deleted file mode 100644 index 8e54fd9..0000000 --- a/OpenSim/Region/Environment/Modules/World/Wind/WindModule.cs +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class WindModule : IWindModule - { -// private static readonly log4net.ILog m_log -// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - private int m_frame = 0; - private int m_frame_mod = 150; - private Random rndnums = new Random(System.Environment.TickCount); - private Scene m_scene = null; - private bool ready = false; - private Vector2[] windSpeeds = new Vector2[16 * 16]; - private Dictionary m_rootAgents = new Dictionary(); - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_frame = 0; - - scene.EventManager.OnFrame += WindUpdate; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; - scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnClientClosed += ClientLoggedOut; - scene.RegisterModuleInterface(this); - - GenWindPos(); - - ready = true; - } - - public void PostInitialise() - { - } - - public void Close() - { - ready = false; - // Remove our hooks - m_scene.EventManager.OnFrame -= WindUpdate; - // m_scene.EventManager.OnNewClient -= SunToClient; - m_scene.EventManager.OnMakeChildAgent -= MakeChildAgent; - m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - m_scene.EventManager.OnClientClosed -= ClientLoggedOut; - } - - public string Name - { - get { return "WindModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public Vector2[] WindSpeeds - { - get { return windSpeeds; } - } - - public void WindToClient(IClientAPI client) - { - if (ready) - { - //if (!sunFixed) - //GenWindPos(); // Generate shared values once - client.SendWindData(windSpeeds); - } - } - - public void WindUpdate() - { - if (((m_frame++ % m_frame_mod) != 0) || !ready) - { - return; - } - //m_log.Debug("[WIND]:Regenerating..."); - GenWindPos(); // Generate shared values once - - //int spotxp = 0; - //int spotyp = 0; - //int spotxm = 0; - //int spotym = 0; - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence avatar in avatars) - { - if (!avatar.IsChildAgent) - { - avatar.ControllingClient.SendWindData(windSpeeds); - } - } - - // set estate settings for region access to sun position - //m_scene.RegionInfo.RegionSettings.SunVector = Position; - //m_scene.RegionInfo.EstateSettings.sunHour = GetLindenEstateHourFromCurrentTime(); - } - - public void ForceWindUpdateToAllClients() - { - GenWindPos(); // Generate shared values once - - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence avatar in avatars) - { - if (!avatar.IsChildAgent) - avatar.ControllingClient.SendWindData(windSpeeds); - } - - // set estate settings for region access to sun position - //m_scene.RegionInfo.RegionSettings.SunVector = Position; - //m_scene.RegionInfo.RegionSettings.SunPosition = GetLindenEstateHourFromCurrentTime(); - } - /// - /// Calculate the sun's orbital position and its velocity. - /// - - private void GenWindPos() - { - for (int y = 0; y < 16; y++) - { - for (int x = 0; x < 16; x++) - { - windSpeeds[y * 16 + x].X = (float)(rndnums.NextDouble() * 2d - 1d); - windSpeeds[y * 16 + x].Y = (float)(rndnums.NextDouble() * 2d - 1d); - } - } - } - - private void ClientLoggedOut(UUID AgentId) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(AgentId)) - { - m_rootAgents.Remove(AgentId); - } - } - } - - private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - m_rootAgents[avatar.UUID] = avatar.RegionHandle; - } - else - { - m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); - WindToClient(avatar.ControllingClient); - } - } - //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); - } - - private void MakeChildAgent(ScenePresence avatar) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - if (m_rootAgents[avatar.UUID] == avatar.RegionHandle) - { - m_rootAgents.Remove(avatar.UUID); - } - } - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs deleted file mode 100644 index cb0ac8c..0000000 --- a/OpenSim/Region/Environment/Modules/World/WorldMap/IMapTileTerrainRenderer.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Drawing; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; - -namespace OpenSim.Region.Environment -{ - public interface IMapTileTerrainRenderer - { - void Initialise(Scene scene, IConfigSource config); - void TerrainToBitmap(Bitmap mapbmp); - } -} diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs deleted file mode 100644 index a806c7d..0000000 --- a/OpenSim/Region/Environment/Modules/World/WorldMap/MapImageModule.cs +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.Reflection; -using Nini.Config; -using OpenMetaverse.Imaging; -using log4net; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenMetaverse; - -namespace OpenSim.Region.Environment.Modules.World.WorldMap -{ - public enum DrawRoutine - { - Rectangle, - Polygon, - Ellipse - } - - public struct face - { - public Point[] pts; - } - - public struct DrawStruct - { - public DrawRoutine dr; - public Rectangle rect; - public SolidBrush brush; - public face[] trns; - } - - public class MapImageModule : IMapImageGenerator, IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - private IConfigSource m_config; - private IMapTileTerrainRenderer terrainRenderer; - - #region IMapImageGenerator Members - - public byte[] WriteJpeg2000Image(string gradientmap) - { - byte[] imageData = null; - - bool drawPrimVolume = true; - bool textureTerrain = true; - - try - { - IConfig startupConfig = m_config.Configs["Startup"]; - drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume); - textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain); - } - catch - { - m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); - } - - if (textureTerrain) - { - terrainRenderer = new TexturedMapTileRenderer(); - } - else - { - terrainRenderer = new ShadedMapTileRenderer(); - } - terrainRenderer.Initialise(m_scene, m_config); - - Bitmap mapbmp = new Bitmap(256, 256); - //long t = System.Environment.TickCount; - //for (int i = 0; i < 10; ++i) { - terrainRenderer.TerrainToBitmap(mapbmp); - //} - //t = System.Environment.TickCount - t; - //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); - - - if (drawPrimVolume) - { - DrawObjectVolume(m_scene, mapbmp); - } - - try - { - imageData = OpenJPEG.EncodeFromImage(mapbmp, true); - } - catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke - { - Console.WriteLine("Failed generating terrain map: " + e); - } - - return imageData; - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - m_config = source; - - IConfig startupConfig = m_config.Configs["Startup"]; - if (startupConfig.GetString("MapImageModule", "MapImageModule") != - "MapImageModule") - return; - - m_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "MapImageModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - -// TODO: unused: -// private void ShadeBuildings(Bitmap map) -// { -// lock (map) -// { -// lock (m_scene.Entities) -// { -// foreach (EntityBase entity in m_scene.Entities.Values) -// { -// if (entity is SceneObjectGroup) -// { -// SceneObjectGroup sog = (SceneObjectGroup) entity; -// -// foreach (SceneObjectPart primitive in sog.Children.Values) -// { -// int x = (int) (primitive.AbsolutePosition.X - (primitive.Scale.X / 2)); -// int y = (int) (primitive.AbsolutePosition.Y - (primitive.Scale.Y / 2)); -// int w = (int) primitive.Scale.X; -// int h = (int) primitive.Scale.Y; -// -// int dx; -// for (dx = x; dx < x + w; dx++) -// { -// int dy; -// for (dy = y; dy < y + h; dy++) -// { -// if (x < 0 || y < 0) -// continue; -// if (x >= map.Width || y >= map.Height) -// continue; -// -// map.SetPixel(dx, dy, Color.DarkGray); -// } -// } -// } -// } -// } -// } -// } -// } - - private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp) - { - int tc = 0; - double[,] hm = whichScene.Heightmap.GetDoubles(); - tc = System.Environment.TickCount; - m_log.Info("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); - List objs = whichScene.GetEntities(); - Dictionary z_sort = new Dictionary(); - //SortedList z_sort = new SortedList(); - List z_sortheights = new List(); - List z_localIDs = new List(); - - lock (objs) - { - foreach (EntityBase obj in objs) - { - // Only draw the contents of SceneObjectGroup - if (obj is SceneObjectGroup) - { - SceneObjectGroup mapdot = (SceneObjectGroup)obj; - Color mapdotspot = Color.Gray; // Default color when prim color is white - // Loop over prim in group - foreach (SceneObjectPart part in mapdot.Children.Values) - { - if (part == null) - continue; - - // Draw if the object is at least 1 meter wide in any direction - if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) - { - // Try to get the RGBA of the default texture entry.. - // - try - { - // get the null checks out of the way - // skip the ones that break - if (part == null) - continue; - - if (part.Shape == null) - continue; - - if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass) - continue; // eliminates trees from this since we don't really have a good tree representation - // if you want tree blocks on the map comment the above line and uncomment the below line - //mapdotspot = Color.PaleGreen; - - if (part.Shape.Textures == null) - continue; - - if (part.Shape.Textures.DefaultTexture == null) - continue; - - Color4 texcolor = part.Shape.Textures.DefaultTexture.RGBA; - - // Not sure why some of these are null, oh well. - - int colorr = 255 - (int)(texcolor.R * 255f); - int colorg = 255 - (int)(texcolor.G * 255f); - int colorb = 255 - (int)(texcolor.B * 255f); - - if (!(colorr == 255 && colorg == 255 && colorb == 255)) - { - //Try to set the map spot color - try - { - // If the color gets goofy somehow, skip it *shakes fist at Color4 - mapdotspot = Color.FromArgb(colorr, colorg, colorb); - } - catch (ArgumentException) - { - } - } - } - catch (IndexOutOfRangeException) - { - // Windows Array - } - catch (ArgumentOutOfRangeException) - { - // Mono Array - } - - Vector3 pos = part.GetWorldPosition(); - - // skip prim outside of retion - if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f) - continue; - - // skip prim in non-finite position - if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) || - Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y)) - continue; - - // Figure out if object is under 256m above the height of the terrain - bool isBelow256AboveTerrain = false; - - try - { - isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f)); - } - catch (Exception) - { - } - - if (isBelow256AboveTerrain) - { - // Translate scale by rotation so scale is represented properly when object is rotated - Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z); - Vector3 scale = new Vector3(); - Vector3 tScale = new Vector3(); - Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z); - - Quaternion llrot = part.GetWorldRotation(); - Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z); - scale = lscale * rot; - - // negative scales don't work in this situation - scale.X = Math.Abs(scale.X); - scale.Y = Math.Abs(scale.Y); - scale.Z = Math.Abs(scale.Z); - - // This scaling isn't very accurate and doesn't take into account the face rotation :P - int mapdrawstartX = (int)(pos.X - scale.X); - int mapdrawstartY = (int)(pos.Y - scale.Y); - int mapdrawendX = (int)(pos.X + scale.X); - int mapdrawendY = (int)(pos.Y + scale.Y); - - // If object is beyond the edge of the map, don't draw it to avoid errors - if (mapdrawstartX < 0 || mapdrawstartX > 255 || mapdrawendX < 0 || mapdrawendX > 255 - || mapdrawstartY < 0 || mapdrawstartY > 255 || mapdrawendY < 0 - || mapdrawendY > 255) - continue; - -#region obb face reconstruction part duex - Vector3[] vertexes = new Vector3[8]; - - // float[] distance = new float[6]; - Vector3[] FaceA = new Vector3[6]; // vertex A for Facei - Vector3[] FaceB = new Vector3[6]; // vertex B for Facei - Vector3[] FaceC = new Vector3[6]; // vertex C for Facei - Vector3[] FaceD = new Vector3[6]; // vertex D for Facei - - tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z); - scale = ((tScale * rot)); - vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - // vertexes[0].x = pos.X + vertexes[0].x; - //vertexes[0].y = pos.Y + vertexes[0].y; - //vertexes[0].z = pos.Z + vertexes[0].z; - - FaceA[0] = vertexes[0]; - FaceB[3] = vertexes[0]; - FaceA[4] = vertexes[0]; - - tScale = lscale; - scale = ((tScale * rot)); - vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - - // vertexes[1].x = pos.X + vertexes[1].x; - // vertexes[1].y = pos.Y + vertexes[1].y; - //vertexes[1].z = pos.Z + vertexes[1].z; - - FaceB[0] = vertexes[1]; - FaceA[1] = vertexes[1]; - FaceC[4] = vertexes[1]; - - tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z); - scale = ((tScale * rot)); - - vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - - //vertexes[2].x = pos.X + vertexes[2].x; - //vertexes[2].y = pos.Y + vertexes[2].y; - //vertexes[2].z = pos.Z + vertexes[2].z; - - FaceC[0] = vertexes[2]; - FaceD[3] = vertexes[2]; - FaceC[5] = vertexes[2]; - - tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z); - scale = ((tScale * rot)); - vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - - //vertexes[3].x = pos.X + vertexes[3].x; - // vertexes[3].y = pos.Y + vertexes[3].y; - // vertexes[3].z = pos.Z + vertexes[3].z; - - FaceD[0] = vertexes[3]; - FaceC[1] = vertexes[3]; - FaceA[5] = vertexes[3]; - - tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z); - scale = ((tScale * rot)); - vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - - // vertexes[4].x = pos.X + vertexes[4].x; - // vertexes[4].y = pos.Y + vertexes[4].y; - // vertexes[4].z = pos.Z + vertexes[4].z; - - FaceB[1] = vertexes[4]; - FaceA[2] = vertexes[4]; - FaceD[4] = vertexes[4]; - - tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z); - scale = ((tScale * rot)); - vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - - // vertexes[5].x = pos.X + vertexes[5].x; - // vertexes[5].y = pos.Y + vertexes[5].y; - // vertexes[5].z = pos.Z + vertexes[5].z; - - FaceD[1] = vertexes[5]; - FaceC[2] = vertexes[5]; - FaceB[5] = vertexes[5]; - - tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z); - scale = ((tScale * rot)); - vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - - // vertexes[6].x = pos.X + vertexes[6].x; - // vertexes[6].y = pos.Y + vertexes[6].y; - // vertexes[6].z = pos.Z + vertexes[6].z; - - FaceB[2] = vertexes[6]; - FaceA[3] = vertexes[6]; - FaceB[4] = vertexes[6]; - - tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z); - scale = ((tScale * rot)); - vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); - - // vertexes[7].x = pos.X + vertexes[7].x; - // vertexes[7].y = pos.Y + vertexes[7].y; - // vertexes[7].z = pos.Z + vertexes[7].z; - - FaceD[2] = vertexes[7]; - FaceC[3] = vertexes[7]; - FaceD[5] = vertexes[7]; -#endregion - - //int wy = 0; - - //bool breakYN = false; // If we run into an error drawing, break out of the - // loop so we don't lag to death on error handling - DrawStruct ds = new DrawStruct(); - ds.brush = new SolidBrush(mapdotspot); - //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY); - - ds.trns = new face[FaceA.Length]; - - for (int i = 0; i < FaceA.Length; i++) - { - Point[] working = new Point[5]; - working[0] = project(FaceA[i], axPos); - working[1] = project(FaceB[i], axPos); - working[2] = project(FaceD[i], axPos); - working[3] = project(FaceC[i], axPos); - working[4] = project(FaceA[i], axPos); - - face workingface = new face(); - workingface.pts = working; - - ds.trns[i] = workingface; - } - - z_sort.Add(part.LocalId, ds); - z_localIDs.Add(part.LocalId); - z_sortheights.Add(pos.Z); - - //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) - //{ - //for (wy = mapdrawstartY; wy < mapdrawendY; wy++) - //{ - //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); - //try - //{ - // Remember, flip the y! - // mapbmp.SetPixel(wx, (255 - wy), mapdotspot); - //} - //catch (ArgumentException) - //{ - // breakYN = true; - //} - - //if (breakYN) - // break; - //} - - //if (breakYN) - // break; - //} - } // Object is within 256m Z of terrain - } // object is at least a meter wide - } // loop over group children - } // entitybase is sceneobject group - } // foreach loop over entities - - float[] sortedZHeights = z_sortheights.ToArray(); - uint[] sortedlocalIds = z_localIDs.ToArray(); - - // Sort prim by Z position - Array.Sort(sortedZHeights, sortedlocalIds); - - Graphics g = Graphics.FromImage(mapbmp); - - for (int s = 0; s < sortedZHeights.Length; s++) - { - if (z_sort.ContainsKey(sortedlocalIds[s])) - { - DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; - for (int r = 0; r < rectDrawStruct.trns.Length; r++ ) - { - g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); - } - //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect); - } - } - - g.Dispose(); - } // lock entities objs - - m_log.Info("[MAPTILE]: Generating Maptile Step 2: Done in " + (System.Environment.TickCount - tc) + " ms"); - return mapbmp; - } - - private Point project(Vector3 point3d, Vector3 originpos) - { - Point returnpt = new Point(); - //originpos = point3d; - //int d = (int)(256f / 1.5f); - - //Vector3 topos = new Vector3(0, 0, 0); - // float z = -point3d.z - topos.z; - - returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d); - returnpt.Y = (int)(255 - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d))); - - return returnpt; - } - -// TODO: unused: -// #region Deprecated Maptile Generation. Adam may update this -// private Bitmap TerrainToBitmap(string gradientmap) -// { -// Bitmap gradientmapLd = new Bitmap(gradientmap); -// -// int pallete = gradientmapLd.Height; -// -// Bitmap bmp = new Bitmap(m_scene.Heightmap.Width, m_scene.Heightmap.Height); -// Color[] colours = new Color[pallete]; -// -// for (int i = 0; i < pallete; i++) -// { -// colours[i] = gradientmapLd.GetPixel(0, i); -// } -// -// lock (m_scene.Heightmap) -// { -// ITerrainChannel copy = m_scene.Heightmap; -// for (int y = 0; y < copy.Height; y++) -// { -// for (int x = 0; x < copy.Width; x++) -// { -// // 512 is the largest possible height before colours clamp -// int colorindex = (int) (Math.Max(Math.Min(1.0, copy[x, y] / 512.0), 0.0) * (pallete - 1)); -// -// // Handle error conditions -// if (colorindex > pallete - 1 || colorindex < 0) -// bmp.SetPixel(x, copy.Height - y - 1, Color.Red); -// else -// bmp.SetPixel(x, copy.Height - y - 1, colours[colorindex]); -// } -// } -// ShadeBuildings(bmp); -// return bmp; -// } -// } -// #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs deleted file mode 100644 index 43ed1e4..0000000 --- a/OpenSim/Region/Environment/Modules/World/WorldMap/MapSearchModule.cs +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Net; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Hypergrid; -using OpenMetaverse; -using log4net; -using Nini.Config; - -namespace OpenSim.Region.Environment.Modules.World.WorldMap -{ - public class MapSearchModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - Scene m_scene = null; // only need one for communication with GridService - List m_scenes = new List(); - - #region IRegionModule Members - public void Initialise(Scene scene, IConfigSource source) - { - if (m_scene == null) - { - m_scene = scene; - } - - m_scenes.Add(scene); - scene.EventManager.OnNewClient += OnNewClient; - } - - public void PostInitialise() - { - } - - public void Close() - { - m_scene = null; - m_scenes.Clear(); - } - - public string Name - { - get { return "MapSearchModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void OnNewClient(IClientAPI client) - { - client.OnMapNameRequest += OnMapNameRequest; - } - - private void OnMapNameRequest(IClientAPI remoteClient, string mapName) - { - if (mapName.Length < 3) - { - remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); - return; - } - - // try to fetch from GridServer - List regionInfos = m_scene.SceneGridService.RequestNamedRegions(mapName, 20); - if (regionInfos == null) - { - m_log.Warn("[MAPSEARCHMODULE]: RequestNamedRegions returned null. Old gridserver?"); - // service wasn't available; maybe still an old GridServer. Try the old API, though it will return only one region - regionInfos = new List(); - RegionInfo info = m_scene.SceneGridService.RequestClosestRegion(mapName); - if (info != null) regionInfos.Add(info); - } - - if ((regionInfos.Count == 0) && IsHypergridOn()) - { - // OK, we tried but there are no regions matching that name. - // Let's check quickly if this is a domain name, and if so link to it - if (mapName.Contains(".") && mapName.Contains(":")) - { - // It probably is a domain name. Try to link to it. - RegionInfo regInfo; - Scene cScene = GetClientScene(remoteClient); - regInfo = HGHyperlink.TryLinkRegion(cScene, remoteClient, mapName); - if (regInfo != null) - regionInfos.Add(regInfo); - } - } - - List blocks = new List(); - - MapBlockData data; - if (regionInfos.Count > 0) - { - foreach (RegionInfo info in regionInfos) - { - data = new MapBlockData(); - data.Agents = 0; - data.Access = 21; // TODO what's this? - data.MapImageId = info.RegionSettings.TerrainImageID; - data.Name = info.RegionName; - data.RegionFlags = 0; // TODO not used? - data.WaterHeight = 0; // not used - data.X = (ushort)info.RegionLocX; - data.Y = (ushort)info.RegionLocY; - blocks.Add(data); - } - } - - // final block, closing the search result - data = new MapBlockData(); - data.Agents = 0; - data.Access = 255; - data.MapImageId = UUID.Zero; - data.Name = mapName; - data.RegionFlags = 0; - data.WaterHeight = 0; // not used - data.X = 0; - data.Y = 0; - blocks.Add(data); - - remoteClient.SendMapBlock(blocks, 0); - } - - private bool IsHypergridOn() - { - return (m_scene.SceneGridService is HGSceneCommunicationService); - } - - private Scene GetClientScene(IClientAPI client) - { - foreach (Scene s in m_scenes) - { - if (client.Scene.RegionInfo.RegionHandle == s.RegionInfo.RegionHandle) - return s; - } - return m_scene; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs deleted file mode 100644 index 7fe538e..0000000 --- a/OpenSim/Region/Environment/Modules/World/WorldMap/ShadedMapTileRenderer.cs +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.Reflection; -using OpenMetaverse; -using OpenMetaverse.Imaging; -using Nini.Config; -using log4net; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.World.WorldMap -{ - public class ShadedMapTileRenderer : IMapTileTerrainRenderer - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - //private IConfigSource m_config; // not used currently - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - // m_config = config; // not used currently - } - - public void TerrainToBitmap(Bitmap mapbmp) - { - int tc = System.Environment.TickCount; - m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); - - double[,] hm = m_scene.Heightmap.GetDoubles(); - bool ShadowDebugContinue = true; - - bool terraincorruptedwarningsaid = false; - - float low = 255; - float high = 0; - for (int x = 0; x < 256; x++) - { - for (int y = 0; y < 256; y++) - { - float hmval = (float)hm[x, y]; - if (hmval < low) - low = hmval; - if (hmval > high) - high = hmval; - } - } - - float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; - - for (int x = 0; x < 256; x++) - { - for (int y = 0; y < 256; y++) - { - // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left - int yr = 255 - y; - - float heightvalue = (float)hm[x, y]; - - if (heightvalue > waterHeight) - { - // scale height value - // No, that doesn't scale it: - // heightvalue = low + mid * (heightvalue - low) / mid; => low + (heightvalue - low) * mid / mid = low + (heightvalue - low) * 1 = low + heightvalue - low = heightvalue - - if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) - heightvalue = 0; - else if (heightvalue > 255f) - heightvalue = 255f; - else if (heightvalue < 0f) - heightvalue = 0f; - - Color color = Color.FromArgb((int)heightvalue, 100, (int)heightvalue); - - mapbmp.SetPixel(x, yr, color); - - try - { - //X - // . - // - // Shade the terrain for shadows - if (x < 255 && yr < 255) - { - float hfvalue = (float)hm[x, y]; - float hfvaluecompare = 0f; - - if ((x + 1 < 256) && (y + 1 < 256)) - { - hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there - } - if (Single.IsInfinity(hfvalue) || Single.IsNaN(hfvalue)) - hfvalue = 0f; - - if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare)) - hfvaluecompare = 0f; - - float hfdiff = hfvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower - - int hfdiffi = 0; - int hfdiffihighlight = 0; - float highlightfactor = 0.18f; - - try - { - // hfdiffi = Math.Abs((int)((hfdiff * 4) + (hfdiff * 0.5))) + 1; - hfdiffi = Math.Abs((int)(hfdiff * 4.5f)) + 1; - if (hfdiff % 1f != 0) - { - // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1); - hfdiffi = hfdiffi + Math.Abs((int)((hfdiff % 1f) * 5f) - 1); - } - - hfdiffihighlight = Math.Abs((int)((hfdiff * highlightfactor) * 4.5f)) + 1; - if (hfdiff % 1f != 0) - { - // hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1); - hfdiffihighlight = hfdiffihighlight + Math.Abs((int)(((hfdiff * highlightfactor) % 1f) * 5f) - 1); - } - } - catch (System.OverflowException) - { - m_log.Debug("[MAPTILE]: Shadow failed at value: " + hfdiff.ToString()); - ShadowDebugContinue = false; - } - - if (hfdiff > 0.3f) - { - // NE is lower than here - // We have to desaturate and lighten the land at the same time - // we use floats, colors use bytes, so shrink are space down to - // 0-255 - - if (ShadowDebugContinue) - { - int r = color.R; - int g = color.G; - int b = color.B; - color = Color.FromArgb((r + hfdiffihighlight < 255) ? r + hfdiffihighlight : 255, - (g + hfdiffihighlight < 255) ? g + hfdiffihighlight : 255, - (b + hfdiffihighlight < 255) ? b + hfdiffihighlight : 255); - } - } - else if (hfdiff < -0.3f) - { - // here is lower than NE: - // We have to desaturate and blacken the land at the same time - // we use floats, colors use bytes, so shrink are space down to - // 0-255 - - if (ShadowDebugContinue) - { - if ((x - 1 > 0) && (yr + 1 < 256)) - { - color = mapbmp.GetPixel(x - 1, yr + 1); - int r = color.R; - int g = color.G; - int b = color.B; - color = Color.FromArgb((r - hfdiffi > 0) ? r - hfdiffi : 0, - (g - hfdiffi > 0) ? g - hfdiffi : 0, - (b - hfdiffi > 0) ? b - hfdiffi : 0); - - mapbmp.SetPixel(x-1, yr+1, color); - } - } - } - } - } - catch (System.ArgumentException) - { - if (!terraincorruptedwarningsaid) - { - m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); - terraincorruptedwarningsaid = true; - } - color = Color.Black; - mapbmp.SetPixel(x, yr, color); - } - } - else - { - // We're under the water level with the terrain, so paint water instead of land - - // Y flip the cordinates - heightvalue = waterHeight - heightvalue; - if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) - heightvalue = 0f; - else if (heightvalue > 19f) - heightvalue = 19f; - else if (heightvalue < 0f) - heightvalue = 0f; - - heightvalue = 100f - (heightvalue * 100f) / 19f; - - try - { - Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255); - mapbmp.SetPixel(x, yr, water); - } - catch (System.ArgumentException) - { - if (!terraincorruptedwarningsaid) - { - m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); - terraincorruptedwarningsaid = true; - } - Color black = Color.Black; - mapbmp.SetPixel(x, (256 - y) - 1, black); - } - } - } - } - m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms"); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs deleted file mode 100644 index d23c352..0000000 --- a/OpenSim/Region/Environment/Modules/World/WorldMap/TexturedMapTileRenderer.cs +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.Reflection; -using OpenMetaverse; -using Nini.Config; -using log4net; -using OpenMetaverse.Imaging; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Environment.Modules.World.Terrain; - -namespace OpenSim.Region.Environment.Modules.World.WorldMap -{ - // Hue, Saturation, Value; used for color-interpolation - struct HSV { - public float h; - public float s; - public float v; - - public HSV(float h, float s, float v) - { - this.h = h; - this.s = s; - this.v = v; - } - - // (for info about algorithm, see http://en.wikipedia.org/wiki/HSL_and_HSV) - public HSV(Color c) - { - float r = c.R / 255f; - float g = c.G / 255f; - float b = c.B / 255f; - float max = Math.Max(Math.Max(r, g), b); - float min = Math.Min(Math.Min(r, g), b); - float diff = max - min; - - if (max == min) h = 0f; - else if (max == r) h = (g - b) / diff * 60f; - else if (max == g) h = (b - r) / diff * 60f + 120f; - else h = (r - g) / diff * 60f + 240f; - if (h < 0f) h += 360f; - - if (max == 0f) s = 0f; - else s = diff / max; - - v = max; - } - - // (for info about algorithm, see http://en.wikipedia.org/wiki/HSL_and_HSV) - public Color toColor() - { - if (s < 0f) Console.WriteLine("S < 0: " + s); - else if (s > 1f) Console.WriteLine("S > 1: " + s); - if (v < 0f) Console.WriteLine("V < 0: " + v); - else if (v > 1f) Console.WriteLine("V > 1: " + v); - - float f = h / 60f; - int sector = (int)f % 6; - f = f - (int)f; - int pi = (int)(v * (1f - s) * 255f); - int qi = (int)(v * (1f - s * f) * 255f); - int ti = (int)(v * (1f - (1f - f) * s) * 255f); - int vi = (int)(v * 255f); - - switch (sector) - { - case 0: - return Color.FromArgb(vi, ti, pi); - case 1: - return Color.FromArgb(qi, vi, pi); - case 2: - return Color.FromArgb(pi, vi, ti); - case 3: - return Color.FromArgb(pi, qi, vi); - case 4: - return Color.FromArgb(ti, pi, vi); - default: - return Color.FromArgb(vi, pi, qi); - } - } - } - - public class TexturedMapTileRenderer : IMapTileTerrainRenderer - { - #region Constants - - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank"). - // The color-values were choosen because they "look right" (at least to me) ;-) - private static readonly UUID defaultTerrainTexture1 = new UUID("0bc58228-74a0-7e83-89bc-5c23464bcec5"); - private static readonly Color defaultColor1 = Color.FromArgb(165, 137, 118); - private static readonly UUID defaultTerrainTexture2 = new UUID("63338ede-0037-c4fd-855b-015d77112fc8"); - private static readonly Color defaultColor2 = Color.FromArgb(69, 89, 49); - private static readonly UUID defaultTerrainTexture3 = new UUID("303cd381-8560-7579-23f1-f0a880799740"); - private static readonly Color defaultColor3 = Color.FromArgb(162, 154, 141); - private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c"); - private static readonly Color defaultColor4 = Color.FromArgb(200, 200, 200); - - #endregion - - - private Scene m_scene; - // private IConfigSource m_config; // not used currently - - // mapping from texture UUIDs to averaged color. This will contain 5-9 values, in general; new values are only - // added when the terrain textures are changed in the estate dialog and a new map is generated (and will stay in - // that map until the region-server restarts. This could be considered a memory-leak, but it's a *very* small one. - // TODO does it make sense to use a "real" cache and regenerate missing entries on fetch? - private Dictionary m_mapping; - - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - // m_config = source; // not used currently - m_mapping = new Dictionary(); - m_mapping.Add(defaultTerrainTexture1, defaultColor1); - m_mapping.Add(defaultTerrainTexture2, defaultColor2); - m_mapping.Add(defaultTerrainTexture3, defaultColor3); - m_mapping.Add(defaultTerrainTexture4, defaultColor4); - m_mapping.Add(Util.BLANK_TEXTURE_UUID, Color.White); - } - - #region Helpers - // This fetches the texture from the asset server synchroneously. That should be ok, as we - // call map-creation only in those places: - // - on start: We can wait here until the asset server returns the texture - // TODO (- on "map" command: We are in the command-line thread, we will wait for completion anyway) - // TODO (- on "automatic" update after some change: We are called from the mapUpdateTimer here and - // will wait anyway) - private Bitmap fetchTexture(UUID id) - { - AssetBase asset = m_scene.AssetCache.GetAsset(id, true); - m_log.DebugFormat("Fetched texture {0}, found: {1}", id, asset != null); - if (asset == null) return null; - - ManagedImage managedImage; - Image image; - - try - { - if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image)) - return new Bitmap(image); - else - return null; - } - catch (DllNotFoundException) - { - m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is emtpy for {0}", id); - - } - catch (IndexOutOfRangeException) - { - m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id); - - } - catch (Exception) - { - m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id); - - } - return null; - - } - - // Compute the average color of a texture. - private Color computeAverageColor(Bitmap bmp) - { - // we have 256 x 256 pixel, each with 256 possible color-values per - // color-channel, so 2^24 is the maximum value we can get, adding everything. - // int is be big enough for that. - int r = 0, g = 0, b = 0; - for (int y = 0; y < bmp.Height; ++y) - { - for (int x = 0; x < bmp.Width; ++x) - { - Color c = bmp.GetPixel(x, y); - r += (int)c.R & 0xff; - g += (int)c.G & 0xff; - b += (int)c.B & 0xff; - } - } - - int pixels = bmp.Width * bmp.Height; - return Color.FromArgb(r / pixels, g / pixels, b / pixels); - } - - // return either the average color of the texture, or the defaultColor if the texturID is invalid - // or the texture couldn't be found - private Color computeAverageColor(UUID textureID, Color defaultColor) { - if (textureID == UUID.Zero) return defaultColor; // not set - if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures - - Bitmap bmp = fetchTexture(textureID); - Color color = bmp == null ? defaultColor : computeAverageColor(bmp); - // store it for future reference - m_mapping[textureID] = color; - - return color; - } - - // S-curve: f(x) = 3x² - 2x³: - // f(0) = 0, f(0.5) = 0.5, f(1) = 1, - // f'(x) = 0 at x = 0 and x = 1; f'(0.5) = 1.5, - // f''(0.5) = 0, f''(x) != 0 for x != 0.5 - private float S(float v) { - return (v * v * (3f - 2f * v)); - } - - // interpolate two colors in HSV space and return the resulting color - private HSV interpolateHSV(ref HSV c1, ref HSV c2, float ratio) { - if (ratio <= 0f) return c1; - if (ratio >= 1f) return c2; - - // make sure we are on the same side on the hue-circle for interpolation - // We change the hue of the parameters here, but we don't change the color - // represented by that value - if (c1.h - c2.h > 180f) c1.h -= 360f; - else if (c2.h - c1.h > 180f) c1.h += 360f; - - return new HSV(c1.h * (1f - ratio) + c2.h * ratio, - c1.s * (1f - ratio) + c2.s * ratio, - c1.v * (1f - ratio) + c2.v * ratio); - } - - // the heigthfield might have some jumps in values. Rendered land is smooth, though, - // as a slope is rendered at that place. So average 4 neighbour values to emulate that. - private float getHeight(double[,] hm, int x, int y) { - if (x < 255 && y < 255) - return (float)(hm[x, y] * .444 + (hm[x + 1, y] + hm[x, y + 1]) * .222 + hm[x + 1, y +1] * .112); - else - return (float)hm[x, y]; - } - #endregion - - public void TerrainToBitmap(Bitmap mapbmp) - { - int tc = System.Environment.TickCount; - m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); - - // These textures should be in the AssetCache anyway, as every client conneting to this - // region needs them. Except on start, when the map is recreated (before anyone connected), - // and on change of the estate settings (textures and terrain values), when the map should - // be recreated. - RegionSettings settings = m_scene.RegionInfo.RegionSettings; - - // the four terrain colors as HSVs for interpolation - HSV hsv1 = new HSV(computeAverageColor(settings.TerrainTexture1, defaultColor1)); - HSV hsv2 = new HSV(computeAverageColor(settings.TerrainTexture2, defaultColor2)); - HSV hsv3 = new HSV(computeAverageColor(settings.TerrainTexture3, defaultColor3)); - HSV hsv4 = new HSV(computeAverageColor(settings.TerrainTexture4, defaultColor4)); - - float levelNElow = (float)settings.Elevation1NE; - float levelNEhigh = (float)settings.Elevation2NE; - - float levelNWlow = (float)settings.Elevation1NW; - float levelNWhigh = (float)settings.Elevation2NW; - - float levelSElow = (float)settings.Elevation1SE; - float levelSEhigh = (float)settings.Elevation2SE; - - float levelSWlow = (float)settings.Elevation1SW; - float levelSWhigh = (float)settings.Elevation2SW; - - float waterHeight = (float)settings.WaterHeight; - - double[,] hm = m_scene.Heightmap.GetDoubles(); - - for (int x = 0; x < 256; x++) - { - float columnRatio = x / 255f; // 0 - 1, for interpolation - for (int y = 0; y < 256; y++) - { - float rowRatio = y / 255f; // 0 - 1, for interpolation - - // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left - int yr = 255 - y; - - float heightvalue = getHeight(hm, x, y); - if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) - heightvalue = 0; - - if (heightvalue > waterHeight) - { - // add a bit noise for breaking up those flat colors: - // - a large-scale noise, for the "patches" (using an doubled s-curve for sharper contrast) - // - a small-scale noise, for bringing in some small scale variation - //float bigNoise = (float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f; // map to 0.0 - 1.0 - //float smallNoise = (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * .5f + .5f; - //float hmod = heightvalue + smallNoise * 3f + S(S(bigNoise)) * 10f; - float hmod = - heightvalue + - (float)TerrainUtil.InterpolatedNoise(x + 33, y + 43) * 1.5f + 1.5f + // 0 - 3 - S(S((float)TerrainUtil.InterpolatedNoise(x / 8.0, y / 8.0) * .5f + .5f)) * 10f; // 0 - 10 - - // find the low/high values for this point (interpolated bilinearily) - // (and remember, x=0,y=0 is SW) - float low = levelSWlow * (1f - rowRatio) * (1f - columnRatio) + - levelSElow * (1f - rowRatio) * columnRatio + - levelNWlow * rowRatio * (1f - columnRatio) + - levelNElow * rowRatio * columnRatio; - float high = levelSWhigh * (1f - rowRatio) * (1f - columnRatio) + - levelSEhigh * (1f - rowRatio) * columnRatio + - levelNWhigh * rowRatio * (1f - columnRatio) + - levelNEhigh * rowRatio * columnRatio; - if (high < low) - { - // someone tried to fool us. High value should be higher than low every time - float tmp = high; - high = low; - low = tmp; - } - - HSV hsv; - if (hmod <= low) hsv = hsv1; // too low - else if (hmod >= high) hsv = hsv4; // too high - else - { - // HSV-interpolate along the colors - // first, rescale h to 0.0 - 1.0 - hmod = (hmod - low) / (high - low); - // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 - if (hmod < 1f/3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f); - else if (hmod < 2f/3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f); - else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f); - } - - // Shade the terrain for shadows - if (x < 255 && y < 255) - { - float hfvaluecompare = getHeight(hm, x + 1, y + 1); // light from north-east => look at land height there - if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare)) - hfvaluecompare = 0f; - - float hfdiff = heightvalue - hfvaluecompare; // => positive if NE is lower, negative if here is lower - hfdiff *= 0.06f; // some random factor so "it looks good" - if (hfdiff > 0.02f) - { - float highlightfactor = 0.18f; - // NE is lower than here - // We have to desaturate and lighten the land at the same time - hsv.s = (hsv.s - (hfdiff * highlightfactor) > 0f) ? hsv.s - (hfdiff * highlightfactor) : 0f; - hsv.v = (hsv.v + (hfdiff * highlightfactor) < 1f) ? hsv.v + (hfdiff * highlightfactor) : 1f; - } - else if (hfdiff < -0.02f) - { - // here is lower than NE: - // We have to desaturate and blacken the land at the same time - hsv.s = (hsv.s + hfdiff > 0f) ? hsv.s + hfdiff : 0f; - hsv.v = (hsv.v + hfdiff > 0f) ? hsv.v + hfdiff : 0f; - } - } - mapbmp.SetPixel(x, yr, hsv.toColor()); - } - else - { - // We're under the water level with the terrain, so paint water instead of land - - heightvalue = waterHeight - heightvalue; - if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) - heightvalue = 0f; - else if (heightvalue > 19f) - heightvalue = 19f; - else if (heightvalue < 0f) - heightvalue = 0f; - - heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0 - - Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255); - mapbmp.SetPixel(x, yr, water); - } - } - } - m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (System.Environment.TickCount - tc) + " ms"); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs deleted file mode 100644 index 37b4547..0000000 --- a/OpenSim/Region/Environment/Modules/World/WorldMap/WorldMapModule.cs +++ /dev/null @@ -1,905 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Net; -using System.Reflection; -using System.Threading; -using OpenMetaverse; -using OpenMetaverse.Imaging; -using OpenMetaverse.StructuredData; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Communications.Capabilities; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Types; -using Caps = OpenSim.Framework.Communications.Capabilities.Caps; - -using OSD = OpenMetaverse.StructuredData.OSD; -using OSDMap = OpenMetaverse.StructuredData.OSDMap; -using OSDArray = OpenMetaverse.StructuredData.OSDArray; - -namespace OpenSim.Region.Environment.Modules.World.WorldMap -{ - public class WorldMapModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly string m_mapLayerPath = "0001/"; - - private OpenSim.Framework.BlockingQueue requests = new OpenSim.Framework.BlockingQueue(); - - //private IConfig m_config; - protected Scene m_scene; - private List cachedMapBlocks = new List(); - private int cachedTime = 0; - private byte[] myMapImageJPEG; - protected bool m_Enabled = false; - private Dictionary m_openRequests = new Dictionary(); - private Dictionary m_blacklistedurls = new Dictionary(); - private Dictionary m_blacklistedregions = new Dictionary(); - private Dictionary m_cachedRegionMapItemsAddress = new Dictionary(); - private List m_rootAgents = new List(); - private Thread mapItemReqThread; - private volatile bool threadrunning = false; - - //private int CacheRegionsDistance = 256; - - #region IRegionModule Members - - public virtual void Initialise(Scene scene, IConfigSource config) - { - IConfig startupConfig = config.Configs["Startup"]; - if (startupConfig.GetString("WorldMapModule", "WorldMap") == - "WorldMap") - m_Enabled = true; - - if (!m_Enabled) - return; - - m_scene = scene; - } - - public virtual void PostInitialise() - { - if (m_Enabled) - AddHandlers(); - } - - public virtual void Close() - { - } - - public virtual string Name - { - get { return "WorldMapModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - protected virtual void AddHandlers() - { - myMapImageJPEG = new byte[0]; - - string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); - regionimage = regionimage.Replace("-", ""); - m_log.Info("[WORLD MAP]: JPEG Map location: http://" + m_scene.RegionInfo.ExternalEndPoint.Address.ToString() + ":" + m_scene.RegionInfo.HttpPort.ToString() + "/index.php?method=" + regionimage); - - m_scene.CommsManager.HttpServer.AddHTTPHandler(regionimage, OnHTTPGetMapImage); - m_scene.CommsManager.HttpServer.AddLLSDHandler( - "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); - - m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; - m_scene.EventManager.OnNewClient += OnNewClient; - m_scene.EventManager.OnClientClosed += ClientLoggedOut; - m_scene.EventManager.OnMakeChildAgent += MakeChildAgent; - m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; - } - - public void OnRegisterCaps(UUID agentID, Caps caps) - { - //m_log.DebugFormat("[WORLD MAP]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); - string capsBase = "/CAPS/" + caps.CapsObjectPath; - caps.RegisterHandler("MapLayer", - new RestStreamHandler("POST", capsBase + m_mapLayerPath, - delegate(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return MapLayerRequest(request, path, param, - agentID, caps); - })); - } - - /// - /// Callback for a map layer request - /// - /// - /// - /// - /// - /// - /// - public string MapLayerRequest(string request, string path, string param, - UUID agentID, Caps caps) - { - //try - //{ - //m_log.DebugFormat("[MAPLAYER]: request: {0}, path: {1}, param: {2}, agent:{3}", - //request, path, param,agentID.ToString()); - - // this is here because CAPS map requests work even beyond the 10,000 limit. - ScenePresence avatarPresence = null; - - m_scene.TryGetAvatar(agentID, out avatarPresence); - - if (avatarPresence != null) - { - bool lookup = false; - - lock (cachedMapBlocks) - { - if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) - { - List mapBlocks; - - mapBlocks = cachedMapBlocks; - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); - } - else - { - lookup = true; - } - } - if (lookup) - { - List mapBlocks; - - mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks((int)m_scene.RegionInfo.RegionLocX - 8, (int)m_scene.RegionInfo.RegionLocY - 8, (int)m_scene.RegionInfo.RegionLocX + 8, (int)m_scene.RegionInfo.RegionLocY + 8); - avatarPresence.ControllingClient.SendMapBlock(mapBlocks,0); - - lock (cachedMapBlocks) - cachedMapBlocks = mapBlocks; - - cachedTime = Util.UnixTimeSinceEpoch(); - } - } - LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); - mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); - return mapResponse.ToString(); - } - - /// - /// - /// - /// - /// - public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq) - { - m_log.Debug("[WORLD MAP]: MapLayer Request in region: " + m_scene.RegionInfo.RegionName); - LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); - mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); - return mapResponse; - } - - /// - /// - /// - /// - protected static OSDMapLayer GetOSDMapLayerResponse() - { - OSDMapLayer mapLayer = new OSDMapLayer(); - mapLayer.Right = 5000; - mapLayer.Top = 5000; - mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); - - return mapLayer; - } - #region EventHandlers - - /// - /// Registered for event - /// - /// - private void OnNewClient(IClientAPI client) - { - client.OnRequestMapBlocks += RequestMapBlocks; - client.OnMapItemRequest += HandleMapItemRequest; - } - - /// - /// Client logged out, check to see if there are any more root agents in the simulator - /// If not, stop the mapItemRequest Thread - /// Event handler - /// - /// AgentID that logged out - private void ClientLoggedOut(UUID AgentId) - { - List presences = m_scene.GetAvatars(); - int rootcount = 0; - for (int i=0;i - /// Starts the MapItemRequest Thread - /// Note that this only gets started when there are actually agents in the region - /// Additionally, it gets stopped when there are none. - /// - /// - private void StartThread(object o) - { - if (threadrunning) return; - threadrunning = true; - m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread"); - mapItemReqThread = new Thread(new ThreadStart(process)); - mapItemReqThread.IsBackground = true; - mapItemReqThread.Name = "MapItemRequestThread"; - mapItemReqThread.Priority = ThreadPriority.BelowNormal; - mapItemReqThread.SetApartmentState(ApartmentState.MTA); - mapItemReqThread.Start(); - ThreadTracker.Add(mapItemReqThread); - } - - /// - /// Enqueues a 'stop thread' MapRequestState. Causes the MapItemRequest thread to end - /// - private void StopThread() - { - MapRequestState st = new MapRequestState(); - st.agentID=UUID.Zero; - st.EstateID=0; - st.flags=0; - st.godlike=false; - st.itemtype=0; - st.regionhandle=0; - - requests.Enqueue(st); - } - - public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, - uint EstateID, bool godlike, uint itemtype, ulong regionhandle) - { - lock (m_rootAgents) - { - if (!m_rootAgents.Contains(remoteClient.AgentId)) - return; - } - uint xstart = 0; - uint ystart = 0; - Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); - if (itemtype == 6) // we only sevice 6 right now (avatar green dots) - { - if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) - { - // Local Map Item Request - List avatars = m_scene.GetAvatars(); - int tc = System.Environment.TickCount; - List mapitems = new List(); - mapItemReply mapitem = new mapItemReply(); - if (avatars.Count == 0 || avatars.Count == 1) - { - mapitem = new mapItemReply(); - mapitem.x = (uint)(xstart + 1); - mapitem.y = (uint)(ystart + 1); - mapitem.id = UUID.Zero; - mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()); - mapitem.Extra = 0; - mapitem.Extra2 = 0; - mapitems.Add(mapitem); - } - else - { - foreach (ScenePresence av in avatars) - { - // Don't send a green dot for yourself - if (av.UUID != remoteClient.AgentId) - { - mapitem = new mapItemReply(); - mapitem.x = (uint)(xstart + av.AbsolutePosition.X); - mapitem.y = (uint)(ystart + av.AbsolutePosition.Y); - mapitem.id = UUID.Zero; - mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()); - mapitem.Extra = 1; - mapitem.Extra2 = 0; - mapitems.Add(mapitem); - } - } - } - remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); - } - else - { - // Remote Map Item Request - - // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. - // Note that we only start up a remote mapItem Request thread if there's users who could - // be making requests - if (!threadrunning) - { - m_log.Warn("[WORLD MAP]: Starting new remote request thread manually. This means that AvatarEnteringParcel never fired! This needs to be fixed! Don't Mantis this, as the developers can see it in this message"); - StartThread(new object()); - } - - RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); - } - } - } - - /// - /// Processing thread main() loop for doing remote mapitem requests - /// - public void process() - { - try - { - while (true) - { - MapRequestState st = requests.Dequeue(); - - // end gracefully - if (st.agentID == UUID.Zero) - { - ThreadTracker.Remove(mapItemReqThread); - break; - } - - bool dorequest = true; - lock (m_rootAgents) - { - if (!m_rootAgents.Contains(st.agentID)) - dorequest = false; - } - - if (dorequest) - { - OSDMap response = RequestMapItemsAsync("", st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); - RequestMapItemsCompleted(response); - } - } - } - catch (Exception e) - { - m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e); - } - - threadrunning = false; - } - - /// - /// Enqueues the map item request into the processing thread - /// - /// - public void EnqueueMapItemRequest(MapRequestState state) - { - requests.Enqueue(state); - } - - /// - /// Sends the mapitem response to the IClientAPI - /// - /// The OSDMap Response for the mapitem - private void RequestMapItemsCompleted(OSDMap response) - { - UUID requestID = response["requestID"].AsUUID(); - - if (requestID != UUID.Zero) - { - MapRequestState mrs = new MapRequestState(); - mrs.agentID = UUID.Zero; - lock (m_openRequests) - { - if (m_openRequests.ContainsKey(requestID)) - { - mrs = m_openRequests[requestID]; - m_openRequests.Remove(requestID); - } - } - - if (mrs.agentID != UUID.Zero) - { - ScenePresence av = null; - m_scene.TryGetAvatar(mrs.agentID, out av); - if (av != null) - { - if (response.ContainsKey(mrs.itemtype.ToString())) - { - List returnitems = new List(); - OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; - for (int i = 0; i < itemarray.Count; i++) - { - OSDMap mapitem = (OSDMap)itemarray[i]; - mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); - returnitems.Add(mi); - } - av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags); - } - } - } - } - } - - /// - /// Enqueue the MapItem request for remote processing - /// - /// blank string, we discover this in the process - /// Agent ID that we are making this request on behalf - /// passed in from packet - /// passed in from packet - /// passed in from packet - /// passed in from packet - /// Region we're looking up - public void RequestMapItems(string httpserver, UUID id, uint flags, - uint EstateID, bool godlike, uint itemtype, ulong regionhandle) - { - MapRequestState st = new MapRequestState(); - st.agentID = id; - st.flags = flags; - st.EstateID = EstateID; - st.godlike = godlike; - st.itemtype = itemtype; - st.regionhandle = regionhandle; - EnqueueMapItemRequest(st); - } - - /// - /// Does the actual remote mapitem request - /// This should be called from an asynchronous thread - /// Request failures get blacklisted until region restart so we don't - /// continue to spend resources trying to contact regions that are down. - /// - /// blank string, we discover this in the process - /// Agent ID that we are making this request on behalf - /// passed in from packet - /// passed in from packet - /// passed in from packet - /// passed in from packet - /// Region we're looking up - /// - private OSDMap RequestMapItemsAsync(string httpserver, UUID id, uint flags, - uint EstateID, bool godlike, uint itemtype, ulong regionhandle) - { - bool blacklisted = false; - lock (m_blacklistedregions) - { - if (m_blacklistedregions.ContainsKey(regionhandle)) - blacklisted = true; - } - - if (blacklisted) - return new OSDMap(); - - UUID requestID = UUID.Random(); - lock (m_cachedRegionMapItemsAddress) - { - if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) - httpserver = m_cachedRegionMapItemsAddress[regionhandle]; - } - if (httpserver.Length == 0) - { - RegionInfo mreg = m_scene.SceneGridService.RequestNeighbouringRegionInfo(regionhandle); - - if (mreg != null) - { - httpserver = "http://" + mreg.ExternalEndPoint.Address.ToString() + ":" + mreg.HttpPort + "/MAP/MapItems/" + regionhandle.ToString(); - lock (m_cachedRegionMapItemsAddress) - { - if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) - m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver); - } - } - else - { - lock (m_blacklistedregions) - { - if (!m_blacklistedregions.ContainsKey(regionhandle)) - m_blacklistedregions.Add(regionhandle, System.Environment.TickCount); - } - m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString()); - } - } - - blacklisted = false; - lock (m_blacklistedurls) - { - if (m_blacklistedurls.ContainsKey(httpserver)) - blacklisted = true; - } - - // Can't find the http server - if (httpserver.Length == 0 || blacklisted) - return new OSDMap(); - - MapRequestState mrs = new MapRequestState(); - mrs.agentID = id; - mrs.EstateID = EstateID; - mrs.flags = flags; - mrs.godlike = godlike; - mrs.itemtype=itemtype; - mrs.regionhandle = regionhandle; - - lock (m_openRequests) - m_openRequests.Add(requestID, mrs); - - WebRequest mapitemsrequest = WebRequest.Create(httpserver); - mapitemsrequest.Method = "POST"; - mapitemsrequest.ContentType = "application/xml+llsd"; - OSDMap RAMap = new OSDMap(); - - // string RAMapString = RAMap.ToString(); - OSD LLSDofRAMap = RAMap; // RENAME if this works - - byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); - OSDMap responseMap = new OSDMap(); - responseMap["requestID"] = OSD.FromUUID(requestID); - - Stream os = null; - try - { // send the Post - mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send - os = mapitemsrequest.GetRequestStream(); - os.Write(buffer, 0, buffer.Length); //Send it - os.Close(); - //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from Sim {0}", httpserver); - } - catch (WebException ex) - { - m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); - lock (m_blacklistedurls) - { - if (!m_blacklistedurls.ContainsKey(httpserver)) - m_blacklistedurls.Add(httpserver, System.Environment.TickCount); - } - - m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); - - return responseMap; - } - - string response_mapItems_reply = null; - { // get the response - try - { - WebResponse webResponse = mapitemsrequest.GetResponse(); - if (webResponse != null) - { - StreamReader sr = new StreamReader(webResponse.GetResponseStream()); - response_mapItems_reply = sr.ReadToEnd().Trim(); - } - else - { - return new OSDMap(); - } - } - catch (WebException) - { - responseMap["connect"] = OSD.FromBoolean(false); - lock (m_blacklistedurls) - { - if (!m_blacklistedurls.ContainsKey(httpserver)) - m_blacklistedurls.Add(httpserver, System.Environment.TickCount); - } - - m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); - - return responseMap; - } - OSD rezResponse = null; - try - { - rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply); - - responseMap = (OSDMap)rezResponse; - responseMap["requestID"] = OSD.FromUUID(requestID); - } - catch (Exception) - { - //m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); - - return responseMap; - } - } - return responseMap; - } - - /// - /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates - /// - /// - /// - /// - /// - public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) - { - List mapBlocks; - if ((flag & 0x10000) != 0) // user clicked on the map a tile that isn't visible - { - List response = new List(); - - // this should return one mapblock at most. But make sure: Look whether the one we requested is in there - mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); - if (mapBlocks != null) - { - foreach (MapBlockData block in mapBlocks) - { - if (block.X == minX && block.Y == minY) - { - // found it => add it to response - response.Add(block); - break; - } - } - } - - if (response.Count == 0) - { - // response still empty => couldn't find the map-tile the user clicked on => tell the client - MapBlockData block = new MapBlockData(); - block.X = (ushort)minX; - block.Y = (ushort)minY; - block.Access = 254; // == not there - response.Add(block); - } - remoteClient.SendMapBlock(response, 0); - } - else - { - // normal mapblock request. Use the provided values - mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, maxX + 4, maxY + 4); - remoteClient.SendMapBlock(mapBlocks, flag); - } - } - - public Hashtable OnHTTPGetMapImage(Hashtable keysvals) - { - m_log.Debug("[WORLD MAP]: Sending map image jpeg"); - Hashtable reply = new Hashtable(); - int statuscode = 200; - byte[] jpeg = new byte[0]; - - if (myMapImageJPEG.Length == 0) - { - MemoryStream imgstream = new MemoryStream(); - Bitmap mapTexture = new Bitmap(1,1); - ManagedImage managedImage; - Image image = (Image)mapTexture; - - try - { - // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data - - imgstream = new MemoryStream(); - - // non-async because we know we have the asset immediately. - AssetBase mapasset = m_scene.AssetCache.GetAsset(m_scene.RegionInfo.lastMapUUID, true); - - // Decode image to System.Drawing.Image - if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) - { - // Save to bitmap - mapTexture = new Bitmap(image); - - EncoderParameters myEncoderParameters = new EncoderParameters(); - myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); - - // Save bitmap to stream - mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters); - - // Write the stream to a byte array for output - jpeg = imgstream.ToArray(); - myMapImageJPEG = jpeg; - } - } - catch (Exception) - { - // Dummy! - m_log.Warn("[WORLD MAP]: Unable to generate Map image"); - } - finally - { - // Reclaim memory, these are unmanaged resources - mapTexture.Dispose(); - image.Dispose(); - imgstream.Close(); - imgstream.Dispose(); - } - } - else - { - // Use cached version so we don't have to loose our mind - jpeg = myMapImageJPEG; - } - - reply["str_response_string"] = Convert.ToBase64String(jpeg); - reply["int_response_code"] = statuscode; - reply["content_type"] = "image/jpeg"; - - return reply; - } - - // From msdn - private static ImageCodecInfo GetEncoderInfo(String mimeType) - { - ImageCodecInfo[] encoders; - encoders = ImageCodecInfo.GetImageEncoders(); - for (int j = 0; j < encoders.Length; ++j) - { - if (encoders[j].MimeType == mimeType) - return encoders[j]; - } - return null; - } - - public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) - { - uint xstart = 0; - uint ystart = 0; - - Utils.LongToUInts(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); - - OSDMap responsemap = new OSDMap(); - List avatars = m_scene.GetAvatars(); - OSDArray responsearr = new OSDArray(avatars.Count); - OSDMap responsemapdata = new OSDMap(); - int tc = System.Environment.TickCount; - /* - foreach (ScenePresence av in avatars) - { - responsemapdata = new OSDMap(); - responsemapdata["X"] = OSD.FromInteger((int)(xstart + av.AbsolutePosition.X)); - responsemapdata["Y"] = OSD.FromInteger((int)(ystart + av.AbsolutePosition.Y)); - responsemapdata["ID"] = OSD.FromUUID(UUID.Zero); - responsemapdata["Name"] = OSD.FromString("TH"); - responsemapdata["Extra"] = OSD.FromInteger(0); - responsemapdata["Extra2"] = OSD.FromInteger(0); - responsearr.Add(responsemapdata); - } - responsemap["1"] = responsearr; - */ - if (avatars.Count == 0) - { - responsemapdata = new OSDMap(); - responsemapdata["X"] = OSD.FromInteger((int)(xstart + 1)); - responsemapdata["Y"] = OSD.FromInteger((int)(ystart + 1)); - responsemapdata["ID"] = OSD.FromUUID(UUID.Zero); - responsemapdata["Name"] = OSD.FromString(Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString())); - responsemapdata["Extra"] = OSD.FromInteger(0); - responsemapdata["Extra2"] = OSD.FromInteger(0); - responsearr.Add(responsemapdata); - - responsemap["6"] = responsearr; - } - else - { - responsearr = new OSDArray(avatars.Count); - foreach (ScenePresence av in avatars) - { - responsemapdata = new OSDMap(); - responsemapdata["X"] = OSD.FromInteger((int)(xstart + av.AbsolutePosition.X)); - responsemapdata["Y"] = OSD.FromInteger((int)(ystart + av.AbsolutePosition.Y)); - responsemapdata["ID"] = OSD.FromUUID(UUID.Zero); - responsemapdata["Name"] = OSD.FromString(Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString())); - responsemapdata["Extra"] = OSD.FromInteger(1); - responsemapdata["Extra2"] = OSD.FromInteger(0); - responsearr.Add(responsemapdata); - } - responsemap["6"] = responsearr; - } - return responsemap; - } - - private void MakeRootAgent(ScenePresence avatar) - { - // You may ask, why this is in a threadpool to start with.. - // The reason is so we don't cause the thread to freeze waiting - // for the 1 second it costs to start a thread manually. - if (!threadrunning) - ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartThread)); - - lock (m_rootAgents) - { - if (!m_rootAgents.Contains(avatar.UUID)) - { - m_rootAgents.Add(avatar.UUID); - } - } - } - - private void MakeChildAgent(ScenePresence avatar) - { - List presences = m_scene.GetAvatars(); - int rootcount = 0; - for (int i = 0; i < presences.Count; i++) - { - if (presences[i] != null) - { - if (!presences[i].IsChildAgent) - rootcount++; - } - } - if (rootcount <= 1) - StopThread(); - - lock (m_rootAgents) - { - if (m_rootAgents.Contains(avatar.UUID)) - { - m_rootAgents.Remove(avatar.UUID); - } - } - } - } - - public struct MapRequestState - { - public UUID agentID; - public uint flags; - public uint EstateID; - public bool godlike; - public uint itemtype; - public ulong regionhandle; - } -} diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index 24865db..73bbb4c 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs @@ -28,7 +28,6 @@ using System; using OpenMetaverse; using OpenSim.Framework; -// using OpenSim.Region.Environment.Modules.Scripting.WorldComm; namespace OpenSim.Region.Framework.Interfaces { diff --git a/OpenSim/Region/Framework/Interfaces/IXMLRPC.cs b/OpenSim/Region/Framework/Interfaces/IXMLRPC.cs index 6570b0a..cdd2b7c 100644 --- a/OpenSim/Region/Framework/Interfaces/IXMLRPC.cs +++ b/OpenSim/Region/Framework/Interfaces/IXMLRPC.cs @@ -28,8 +28,6 @@ using OpenMetaverse; using Nwc.XmlRpc; -// using OpenSim.Region.Environment.Modules.Scripting.XMLRPC; - namespace OpenSim.Region.Framework.Interfaces { public interface IXmlRpcRequestInfo diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs index bd9c260..cc82a48 100644 --- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs +++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs @@ -40,7 +40,6 @@ using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Servers; -// using OpenSim.Region.Environment; using OpenSim.Region.Framework.Scenes; //using HyperGrid.Framework; diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs index ba81270..c6d2bfc 100644 --- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs @@ -40,7 +40,6 @@ using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Servers; -// using OpenSim.Region.Environment; using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.Framework.Scenes.Hypergrid diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.cs index a52fdc6..1cb98db 100644 --- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.cs +++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.cs @@ -34,7 +34,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications.Cache; -// using OpenSim.Region.Environment; using OpenSim.Region.Framework.Scenes; using TPFlags = OpenSim.Framework.Constants.TeleportFlags; diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGSceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGSceneCommunicationService.cs index d0dc4f7..a17df71 100644 --- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGSceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGSceneCommunicationService.cs @@ -39,7 +39,6 @@ using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Communications.Capabilities; using OpenSim.Region.Framework.Scenes; -// using OpenSim.Region.Environment; using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.Framework.Scenes.Hypergrid diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index dc27a55..096b2cb 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -37,7 +37,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Setup; -namespace OpenSim.Region.Environment.Scenes.Tests +namespace OpenSim.Region.CoreModules.Scenes.Tests { /// /// Basic scene object tests (create, read and delete but not update). diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs index 3efb886..3e0f48f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs @@ -37,7 +37,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Setup; -namespace OpenSim.Region.Environment.Scenes.Tests +namespace OpenSim.Region.CoreModules.Scenes.Tests { /// /// Linking tests diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index ec36be9..2053c8f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -36,8 +36,8 @@ using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.Communications.Local; -using OpenSim.Region.Environment.Modules.World.Serialiser; +using OpenSim.Region.CoreModules.Communications.Local; +using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Setup; diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs index 0b9937a..5d2839c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs @@ -32,7 +32,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.Communications.REST; +using OpenSim.Region.CoreModules.Communications.REST; using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Setup; diff --git a/OpenSim/Region/Modules/Python/Properties/AssemblyInfo.cs b/OpenSim/Region/Modules/Python/Properties/AssemblyInfo.cs deleted file mode 100644 index 63e574a..0000000 --- a/OpenSim/Region/Modules/Python/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Python")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Python")] -[assembly: AssemblyCopyright("Copyright (c) 2008")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("5bd55f67-385d-4a43-893a-b5d2ea43f07d")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/Modules/Python/PythonAPI/Console.cs b/OpenSim/Region/Modules/Python/PythonAPI/Console.cs deleted file mode 100644 index 215a9ad..0000000 --- a/OpenSim/Region/Modules/Python/PythonAPI/Console.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using log4net; - -namespace OpenSim.Region.Modules.Python.PythonAPI -{ - class Console - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public void WriteLine(string txt) - { - m_log.Info(txt); - } - - public void WriteLine(string txt, params Object[] e) - { - m_log.Info(String.Format(txt, e)); - } - } -} diff --git a/OpenSim/Region/Modules/Python/PythonModule.cs b/OpenSim/Region/Modules/Python/PythonModule.cs deleted file mode 100644 index 5dedac2..0000000 --- a/OpenSim/Region/Modules/Python/PythonModule.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Security.Policy; -using System.Text; -using IronPython.Hosting; -using log4net; -using Nini.Config; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Modules.Python -{ - class PythonModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private PythonEngine m_python; - - public void Initialise(Scene scene, IConfigSource source) - { - } - - public void PostInitialise() - { - m_log.Info("[PYTHON] Initialising IronPython engine."); - m_python = new PythonEngine(); - m_python.AddToPath(System.Environment.CurrentDirectory + System.IO.Path.DirectorySeparatorChar + "Python"); - } - - public void Close() - { - } - - public string Name - { - get { return "PythonModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - } -} diff --git a/OpenSim/Region/Modules/SvnSerialiser/Properties/AssemblyInfo.cs b/OpenSim/Region/Modules/SvnSerialiser/Properties/AssemblyInfo.cs deleted file mode 100644 index 165fcea..0000000 --- a/OpenSim/Region/Modules/SvnSerialiser/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// General information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SvnSerialiser")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SvnSerialiser")] -[assembly: AssemblyCopyright("Copyright (c) 2008")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c0893655-0c18-4dd7-8b5b-5f58ab1ec6c7")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/Modules/SvnSerialiser/SvnBackupModule.cs b/OpenSim/Region/Modules/SvnSerialiser/SvnBackupModule.cs deleted file mode 100644 index 6e3b620..0000000 --- a/OpenSim/Region/Modules/SvnSerialiser/SvnBackupModule.cs +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Timers; -using log4net; -using Nini.Config; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.World.Serialiser; -using OpenSim.Region.Environment.Modules.World.Terrain; -using OpenSim.Region.Framework.Scenes; -using PumaCode.SvnDotNet.AprSharp; -using PumaCode.SvnDotNet.SubversionSharp; -using Slash=System.IO.Path; - -namespace OpenSim.Region.Modules.SvnSerialiser -{ - public class SvnBackupModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private readonly List m_scenes = new List(); - private readonly Timer m_timer = new Timer(); - - private bool m_enabled = false; - private bool m_installBackupOnLoad = false; - private IRegionSerialiserModule m_serialiser; - private bool m_svnAutoSave = false; - private SvnClient m_svnClient; - private string m_svndir = "SVNmodule" + Slash.DirectorySeparatorChar + "repo"; - private string m_svnpass = "password"; - - private TimeSpan m_svnperiod = new TimeSpan(0, 0, 15, 0, 0); - private string m_svnurl = "svn://insert.Your.svn/here/"; - private string m_svnuser = "username"; - - #region SvnModule Core - - /// - /// Exports a specified scene to the SVN repo directory, then commits. - /// - /// The scene to export - public void SaveRegion(Scene scene) - { - List svnfilenames = CreateAndAddExport(scene); - - m_svnClient.Commit3(svnfilenames, true, false); - m_log.Info("[SVNBACKUP]: Region backup successful (" + scene.RegionInfo.RegionName + ")."); - } - - /// - /// Saves all registered scenes to the SVN repo, then commits. - /// - public void SaveAllRegions() - { - List svnfilenames = new List(); - List regions = new List(); - - foreach (Scene scene in m_scenes) - { - svnfilenames.AddRange(CreateAndAddExport(scene)); - regions.Add("'" + scene.RegionInfo.RegionName + "' "); - } - - m_svnClient.Commit3(svnfilenames, true, false); - m_log.Info("[SVNBACKUP]: Server backup successful (" + String.Concat(regions.ToArray()) + ")."); - } - - private List CreateAndAddExport(Scene scene) - { - m_log.Info("[SVNBACKUP]: Saving a region to SVN with name " + scene.RegionInfo.RegionName); - - List filenames = m_serialiser.SerialiseRegion(scene, m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID + Slash.DirectorySeparatorChar); - - try - { - m_svnClient.Add3(m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID, true, false, false); - } - catch (SvnException) - { - } - - List svnfilenames = new List(); - foreach (string filename in filenames) - svnfilenames.Add(m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID + Slash.DirectorySeparatorChar + filename); - svnfilenames.Add(m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID); - - return svnfilenames; - } - - public void LoadRegion(Scene scene) - { - IRegionSerialiserModule serialiser = scene.RequestModuleInterface(); - if (serialiser != null) - { - serialiser.LoadPrimsFromXml2( - scene, - m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID - + Slash.DirectorySeparatorChar + "objects.xml"); - - scene.RequestModuleInterface().LoadFromFile( - m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID - + Slash.DirectorySeparatorChar + "heightmap.r32"); - - m_log.Info("[SVNBACKUP]: Region load successful (" + scene.RegionInfo.RegionName + ")."); - } - else - { - m_log.ErrorFormat( - "[SVNBACKUP]: Region load of {0} failed - no serialisation module available", - scene.RegionInfo.RegionName); - } - } - - private void CheckoutSvn() - { - m_svnClient.Checkout2(m_svnurl, m_svndir, Svn.Revision.Head, Svn.Revision.Head, true, false); - } - - private void CheckoutSvn(SvnRevision revision) - { - m_svnClient.Checkout2(m_svnurl, m_svndir, revision, revision, true, false); - } - - // private void CheckoutSvnPartial(string subdir) - // { - // if (!Directory.Exists(m_svndir + Slash.DirectorySeparatorChar + subdir)) - // Directory.CreateDirectory(m_svndir + Slash.DirectorySeparatorChar + subdir); - - // m_svnClient.Checkout2(m_svnurl + "/" + subdir, m_svndir, Svn.Revision.Head, Svn.Revision.Head, true, false); - // } - - // private void CheckoutSvnPartial(string subdir, SvnRevision revision) - // { - // if (!Directory.Exists(m_svndir + Slash.DirectorySeparatorChar + subdir)) - // Directory.CreateDirectory(m_svndir + Slash.DirectorySeparatorChar + subdir); - - // m_svnClient.Checkout2(m_svnurl + "/" + subdir, m_svndir, revision, revision, true, false); - // } - - #endregion - - #region SvnDotNet Callbacks - - private SvnError SimpleAuth(out SvnAuthCredSimple svnCredentials, IntPtr baton, - AprString realm, AprString username, bool maySave, AprPool pool) - { - svnCredentials = SvnAuthCredSimple.Alloc(pool); - svnCredentials.Username = new AprString(m_svnuser, pool); - svnCredentials.Password = new AprString(m_svnpass, pool); - svnCredentials.MaySave = false; - return SvnError.NoError; - } - - private SvnError GetCommitLogCallback(out AprString logMessage, out SvnPath tmpFile, AprArray commitItems, IntPtr baton, AprPool pool) - { - if (!commitItems.IsNull) - { - foreach (SvnClientCommitItem2 item in commitItems) - { - m_log.Debug("[SVNBACKUP]: ... " + Path.GetFileName(item.Path.ToString()) + " (" + item.Kind.ToString() + ") r" + item.Revision.ToString()); - } - } - - string msg = "Region Backup (" + System.Environment.MachineName + " at " + DateTime.UtcNow + " UTC)"; - - m_log.Debug("[SVNBACKUP]: Saved with message: " + msg); - - logMessage = new AprString(msg, pool); - tmpFile = new SvnPath(pool); - - return (SvnError.NoError); - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - try - { - if (!source.Configs["SVN"].GetBoolean("Enabled", false)) - return; - - m_enabled = true; - - m_svndir = source.Configs["SVN"].GetString("Directory", m_svndir); - m_svnurl = source.Configs["SVN"].GetString("URL", m_svnurl); - m_svnuser = source.Configs["SVN"].GetString("Username", m_svnuser); - m_svnpass = source.Configs["SVN"].GetString("Password", m_svnpass); - m_installBackupOnLoad = source.Configs["SVN"].GetBoolean("ImportOnStartup", m_installBackupOnLoad); - m_svnAutoSave = source.Configs["SVN"].GetBoolean("Autosave", m_svnAutoSave); - m_svnperiod = new TimeSpan(0, source.Configs["SVN"].GetInt("AutosavePeriod", (int) m_svnperiod.TotalMinutes), 0); - } - catch (Exception) - { - } - - lock (m_scenes) - { - m_scenes.Add(scene); - } - //Only register it once, to prevent command being executed x*region times - if (m_scenes.Count == 1) - { - scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; - } - } - - public void PostInitialise() - { - if (m_enabled == false) - return; - - if (m_svnAutoSave) - { - m_timer.Interval = m_svnperiod.TotalMilliseconds; - m_timer.Elapsed += m_timer_Elapsed; - m_timer.AutoReset = true; - m_timer.Start(); - } - - m_log.Info("[SVNBACKUP]: Connecting to SVN server " + m_svnurl + " ..."); - SetupSvnProvider(); - - m_log.Info("[SVNBACKUP]: Creating repository in " + m_svndir + "."); - CreateSvnDirectory(); - CheckoutSvn(); - SetupSerialiser(); - - if (m_installBackupOnLoad) - { - m_log.Info("[SVNBACKUP]: Importing latest SVN revision to scenes..."); - foreach (Scene scene in m_scenes) - { - LoadRegion(scene); - } - } - } - - public void Close() - { - } - - public string Name - { - get { return "SvnBackupModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void EventManager_OnPluginConsole(string[] args) - { - if (args[0] == "svn" && args[1] == "save") - { - SaveAllRegions(); - } - if (args.Length == 2) - { - if (args[0] == "svn" && args[1] == "load") - { - LoadAllScenes(); - } - } - if (args.Length == 3) - { - if (args[0] == "svn" && args[1] == "load") - { - LoadAllScenes(Int32.Parse(args[2])); - } - } - if (args.Length == 3) - { - if (args[0] == "svn" && args[1] == "load-region") - { - LoadScene(args[2]); - } - } - if (args.Length == 4) - { - if (args[0] == "svn" && args[1] == "load-region") - { - LoadScene(args[2], Int32.Parse(args[3])); - } - } - } - - public void LoadScene(string name) - { - CheckoutSvn(); - - foreach (Scene scene in m_scenes) - { - if (scene.RegionInfo.RegionName.ToLower().Equals(name.ToLower())) - { - LoadRegion(scene); - return; - } - } - m_log.Warn("[SVNBACKUP]: No region loaded - unable to find matching name."); - } - - public void LoadScene(string name, int revision) - { - CheckoutSvn(new SvnRevision(revision)); - - foreach (Scene scene in m_scenes) - { - if (scene.RegionInfo.RegionName.ToLower().Equals(name.ToLower())) - { - LoadRegion(scene); - return; - } - } - m_log.Warn("[SVNBACKUP]: No region loaded - unable to find matching name."); - } - - public void LoadAllScenes() - { - CheckoutSvn(); - - foreach (Scene scene in m_scenes) - { - LoadRegion(scene); - } - } - - public void LoadAllScenes(int revision) - { - CheckoutSvn(new SvnRevision(revision)); - - foreach (Scene scene in m_scenes) - { - LoadRegion(scene); - } - } - - private void m_timer_Elapsed(object sender, ElapsedEventArgs e) - { - SaveAllRegions(); - } - - private void SetupSerialiser() - { - if (m_scenes.Count > 0) - m_serialiser = m_scenes[0].RequestModuleInterface(); - } - - private void SetupSvnProvider() - { - m_svnClient = new SvnClient(); - m_svnClient.AddUsernameProvider(); - m_svnClient.AddPromptProvider(new SvnAuthProviderObject.SimplePrompt(SimpleAuth), IntPtr.Zero, 2); - m_svnClient.OpenAuth(); - m_svnClient.Context.LogMsgFunc2 = new SvnDelegate(new SvnClient.GetCommitLog2(GetCommitLogCallback)); - } - - private void CreateSvnDirectory() - { - if (!Directory.Exists(m_svndir)) - Directory.CreateDirectory(m_svndir); - } - } -} diff --git a/OpenSim/Region/Modules/Terrain/Extensions/DefaultEffects/Effects/ChannelDigger.cs b/OpenSim/Region/Modules/Terrain/Extensions/DefaultEffects/Effects/ChannelDigger.cs deleted file mode 100644 index 8dd7478..0000000 --- a/OpenSim/Region/Modules/Terrain/Extensions/DefaultEffects/Effects/ChannelDigger.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.World.Terrain; -using OpenSim.Region.Environment.Modules.World.Terrain.FloodBrushes; - -namespace OpenSim.Region.Modules.Terrain.Extensions.DefaultEffects.Effects -{ - public class ChannelDigger : ITerrainEffect - { - private readonly int num_h = 4; - private readonly int num_w = 4; - - private readonly ITerrainFloodEffect raiseFunction = new RaiseArea(); - private readonly ITerrainFloodEffect smoothFunction = new SmoothArea(); - - #region ITerrainEffect Members - - public void RunEffect(ITerrainChannel map) - { - FillMap(map, 15); - BuildTiles(map, 7); - SmoothMap(map, 3); - } - - #endregion - - private void SmoothMap(ITerrainChannel map, int rounds) - { - Boolean[,] bitmap = new bool[map.Width,map.Height]; - for (int x = 0; x < map.Width; x++) - { - for (int y = 0; y < map.Height; y++) - { - bitmap[x, y] = true; - } - } - - for (int i = 0; i < rounds; i++) - { - smoothFunction.FloodEffect(map, bitmap, 1.0); - } - } - - private void FillMap(ITerrainChannel map, double val) - { - for (int x = 0; x < map.Width; x++) - for (int y = 0; y < map.Height; y++) - map[x, y] = val; - } - - private void BuildTiles(ITerrainChannel map, double height) - { - int channelWidth = (int) Math.Floor((map.Width / num_w) * 0.8); - int channelHeight = (int) Math.Floor((map.Height / num_h) * 0.8); - int channelXOffset = (map.Width / num_w) - channelWidth; - int channelYOffset = (map.Height / num_h) - channelHeight; - - for (int x = 0; x < num_w; x++) - { - for (int y = 0; y < num_h; y++) - { - int xoff = ((channelXOffset + channelWidth) * x) + (channelXOffset / 2); - int yoff = ((channelYOffset + channelHeight) * y) + (channelYOffset / 2); - - Boolean[,] bitmap = new bool[map.Width,map.Height]; - - for (int dx = 0; dx < channelWidth; dx++) - { - for (int dy = 0; dy < channelHeight; dy++) - { - bitmap[dx + xoff, dy + yoff] = true; - } - } - - raiseFunction.FloodEffect(map, bitmap, height); - } - } - } - } -} diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs new file mode 100644 index 0000000..167f0cc --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs @@ -0,0 +1,628 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text.RegularExpressions; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Avatar.Chat +{ + + // An instance of this class exists for each unique combination of + // IRC chat interface characteristics, as determined by the supplied + // configuration file. + + internal class ChannelState + { + + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static Regex arg = new Regex(@"\[[^\[\]]*\]"); + private static int _idk_ = 0; + private static int DEBUG_CHANNEL = 2147483647; + + // These are the IRC Connector configurable parameters with hard-wired + // default values (retained for compatability). + + internal string Server = null; + internal string Password = null; + internal string IrcChannel = null; + internal string BaseNickname = "OSimBot"; + internal uint Port = 6667; + internal string User = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot"; + + internal bool ClientReporting = true; + internal bool RelayChat = true; + internal bool RelayPrivateChannels = false; + internal int RelayChannel = 1; + internal List ValidInWorldChannels = new List(); + + // Connector agnostic parameters. These values are NOT shared with the + // connector and do not differentiate at an IRC level + + internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}"; + internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}"; + internal int RelayChannelOut = -1; + internal bool RandomizeNickname = true; + internal bool CommandsEnabled = false; + internal int CommandChannel = -1; + internal int ConnectDelay = 10; + internal int PingDelay = 15; + internal string DefaultZone = "Sim"; + + internal string _accessPassword = String.Empty; + internal Regex AccessPasswordRegex = null; + internal string AccessPassword + { + get { return _accessPassword; } + set + { + _accessPassword = value; + AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?[^,]+),\s*(?.+)$", _accessPassword), + RegexOptions.Compiled); + } + } + + + + // IRC connector reference + + internal IRCConnector irc = null; + + internal int idn = _idk_++; + + // List of regions dependent upon this connection + + internal List clientregions = new List(); + + // Needed by OpenChannel + + internal ChannelState() + { + } + + // This constructor is used by the Update* methods. A copy of the + // existing channel state is created, and distinguishing characteristics + // are copied across. + + internal ChannelState(ChannelState model) + { + Server = model.Server; + Password = model.Password; + IrcChannel = model.IrcChannel; + Port = model.Port; + BaseNickname = model.BaseNickname; + RandomizeNickname = model.RandomizeNickname; + User = model.User; + CommandsEnabled = model.CommandsEnabled; + CommandChannel = model.CommandChannel; + RelayChat = model.RelayChat; + RelayPrivateChannels = model.RelayPrivateChannels; + RelayChannelOut = model.RelayChannelOut; + RelayChannel = model.RelayChannel; + ValidInWorldChannels = model.ValidInWorldChannels; + PrivateMessageFormat = model.PrivateMessageFormat; + NoticeMessageFormat = model.NoticeMessageFormat; + ClientReporting = model.ClientReporting; + AccessPassword = model.AccessPassword; + DefaultZone = model.DefaultZone; + ConnectDelay = model.ConnectDelay; + PingDelay = model.PingDelay; + } + + // Read the configuration file, performing variable substitution and any + // necessary aliasing. See accompanying documentation for how this works. + // If you don't need variables, then this works exactly as before. + // If either channel or server are not specified, the request fails. + + internal static void OpenChannel(RegionState rs, IConfig config) + { + + // Create a new instance of a channel. This may not actually + // get used if an equivalent channel already exists. + + ChannelState cs = new ChannelState(); + + // Read in the configuration file and filter everything for variable + // subsititution. + + m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region); + + cs.Server = Substitute(rs, config.GetString("server", null)); + m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server); + cs.Password = Substitute(rs, config.GetString("password", null)); + // probably not a good idea to put a password in the log file + cs.IrcChannel = Substitute(rs, config.GetString("channel", null)); + m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel); + cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port)))); + m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port); + cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname)); + m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname); + cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname)))); + m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); + cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname)))); + m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname); + cs.User = Substitute(rs, config.GetString("username", cs.User)); + m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User); + cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled)))); + m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled); + cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel)))); + m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); + cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel)))); + m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel); + cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat)))); + m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat); + cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels)))); + m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); + cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels)))); + m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels); + cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut)))); + m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut); + cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel)))); + m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); + cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel)))); + m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel); + cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat)); + m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat); + cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat)); + m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat); + cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting?"1":"0"))) > 0; + m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); + cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting)))); + m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting); + cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone)); + m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone); + cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay)))); + m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay); + cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay)))); + m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay); + cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword)); + m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword); + + + // Fail if fundamental information is still missing + + if (cs.Server == null || cs.IrcChannel == null || cs.BaseNickname == null || cs.User == null) + throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}", cs.idn, rs.Region)); + + m_log.InfoFormat("[IRC-Channel-{0}] Configuration for Region {1} is valid", cs.idn, rs.Region); + m_log.InfoFormat("[IRC-Channel-{0}] Server = {1}", cs.idn, cs.Server); + m_log.InfoFormat("[IRC-Channel-{0}] Channel = {1}", cs.idn, cs.IrcChannel); + m_log.InfoFormat("[IRC-Channel-{0}] Port = {1}", cs.idn, cs.Port); + m_log.InfoFormat("[IRC-Channel-{0}] Nickname = {1}", cs.idn, cs.BaseNickname); + m_log.InfoFormat("[IRC-Channel-{0}] User = {1}", cs.idn, cs.User); + + // Set the channel state for this region + + if (cs.RelayChat) + { + cs.ValidInWorldChannels.Add(0); + cs.ValidInWorldChannels.Add(DEBUG_CHANNEL); + } + + if (cs.RelayPrivateChannels) + cs.ValidInWorldChannels.Add(cs.RelayChannelOut); + + rs.cs = Integrate(rs, cs); + + } + + // An initialized channel state instance is passed in. If an identical + // channel state instance already exists, then the existing instance + // is used to replace the supplied value. + // If the instance matches with respect to IRC, then the underlying + // IRCConnector is assigned to the supplied channel state and the + // updated value is returned. + // If there is no match, then the supplied instance is completed by + // creating and assigning an instance of an IRC connector. + + private static ChannelState Integrate(RegionState rs, ChannelState p_cs) + { + + ChannelState cs = p_cs; + + // Check to see if we have an existing server/channel setup that can be used + // In the absence of variable substitution this will always resolve to the + // same ChannelState instance, and the table will only contains a single + // entry, so the performance considerations for the existing behavior are + // zero. Only the IRC connector is shared, the ChannelState still contains + // values that, while independent of the IRC connetion, do still distinguish + // this region's behavior. + + lock (IRCBridgeModule.m_channels) + { + + foreach (ChannelState xcs in IRCBridgeModule.m_channels) + { + if (cs.IsAPerfectMatchFor(xcs)) + { + m_log.DebugFormat("[IRC-Channel-{0}] Channel state matched", cs.idn); + cs = xcs; + break; + } + if (cs.IsAConnectionMatchFor(xcs)) + { + m_log.DebugFormat("[IRC-Channel-{0}] Channel matched", cs.idn); + cs.irc = xcs.irc; + break; + } + } + + } + + // No entry was found, so this is going to be a new entry. + + if (cs.irc == null) + { + + m_log.DebugFormat("[IRC-Channel-{0}] New channel required", cs.idn); + + if ((cs.irc = new IRCConnector(cs)) != null) + { + + IRCBridgeModule.m_channels.Add(cs); + + m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}", + cs.idn, rs.Region, cs.DefaultZone, + cs.CommandsEnabled ? "enabled" : "not enabled", + cs.RelayPrivateChannels ? "relayed" : "not relayed"); + } + else + { + string txt = String.Format("[IRC-Channel-{0}] Region {1} failed to connect to channel {2} on server {3}:{4}", + cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port); + m_log.Error(txt); + throw new Exception(txt); + } + } + else + { + m_log.InfoFormat("[IRC-Channel-{0}] Region {1} reusing existing connection to channel {2} on server {3}:{4}", + cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port); + } + + m_log.InfoFormat("[IRC-Channel-{0}] Region {1} associated with channel {2} on server {3}:{4}", + cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port); + + // We're finally ready to commit ourselves + + + return cs; + + } + + // These routines allow differentiating changes to + // the underlying channel state. If necessary, a + // new channel state will be created. + + internal ChannelState UpdateServer(RegionState rs, string server) + { + RemoveRegion(rs); + ChannelState cs = new ChannelState(this); + cs.Server = server; + cs = Integrate(rs, cs); + cs.AddRegion(rs); + return cs; + } + + internal ChannelState UpdatePort(RegionState rs, string port) + { + RemoveRegion(rs); + ChannelState cs = new ChannelState(this); + cs.Port = Convert.ToUInt32(port); + cs = Integrate(rs, cs); + cs.AddRegion(rs); + return cs; + } + + internal ChannelState UpdateChannel(RegionState rs, string channel) + { + RemoveRegion(rs); + ChannelState cs = new ChannelState(this); + cs.IrcChannel = channel; + cs = Integrate(rs, cs); + cs.AddRegion(rs); + return cs; + } + + internal ChannelState UpdateNickname(RegionState rs, string nickname) + { + RemoveRegion(rs); + ChannelState cs = new ChannelState(this); + cs.BaseNickname = nickname; + cs = Integrate(rs, cs); + cs.AddRegion(rs); + return cs; + } + + internal ChannelState UpdateClientReporting(RegionState rs, string cr) + { + RemoveRegion(rs); + ChannelState cs = new ChannelState(this); + cs.ClientReporting = Convert.ToBoolean(cr); + cs = Integrate(rs, cs); + cs.AddRegion(rs); + return cs; + } + + internal ChannelState UpdateRelayIn(RegionState rs, string channel) + { + RemoveRegion(rs); + ChannelState cs = new ChannelState(this); + cs.RelayChannel = Convert.ToInt32(channel); + cs = Integrate(rs, cs); + cs.AddRegion(rs); + return cs; + } + + internal ChannelState UpdateRelayOut(RegionState rs, string channel) + { + RemoveRegion(rs); + ChannelState cs = new ChannelState(this); + cs.RelayChannelOut = Convert.ToInt32(channel); + cs = Integrate(rs, cs); + cs.AddRegion(rs); + return cs; + } + + // Determine whether or not this is a 'new' channel. Only those + // attributes that uniquely distinguish an IRC connection should + // be included here (and only those attributes should really be + // in the ChannelState structure) + + private bool IsAConnectionMatchFor(ChannelState cs) + { + return ( + Server == cs.Server && + IrcChannel == cs.IrcChannel && + Port == cs.Port && + BaseNickname == cs.BaseNickname && + User == cs.User + ); + } + + // This level of obsessive matching allows us to produce + // a minimal overhead int he case of a server which does + // need to differentiate IRC at a region level. + + private bool IsAPerfectMatchFor(ChannelState cs) + { + return ( IsAConnectionMatchFor(cs) && + RelayChannelOut == cs.RelayChannelOut && + PrivateMessageFormat == cs.PrivateMessageFormat && + NoticeMessageFormat == cs.NoticeMessageFormat && + RandomizeNickname == cs.RandomizeNickname && + AccessPassword == cs.AccessPassword && + CommandsEnabled == cs.CommandsEnabled && + CommandChannel == cs.CommandChannel && + DefaultZone == cs.DefaultZone && + RelayPrivateChannels == cs.RelayPrivateChannels && + RelayChannel == cs.RelayChannel && + RelayChat == cs.RelayChat && + ClientReporting == cs.ClientReporting + ); + } + + // This function implements the variable substitution mechanism + // for the configuration values. Each string read from the + // configuration file is scanned for '[...]' enclosures. Each + // one that is found is replaced by either a runtime variable + // (%xxx) or an existing configuration key. When no further + // substitution is possible, the remaining string is returned + // to the caller. This allows for arbitrarily nested + // enclosures. + + private static string Substitute(RegionState rs, string instr) + { + + string result = instr; + + if (result == null || result.Length == 0) + return result; + + // Repeatedly scan the string until all possible + // substitutions have been performed. + + // m_log.DebugFormat("[IRC-Channel] Parse[1]: {0}", result); + + while (arg.IsMatch(result)) + { + + string vvar = arg.Match(result).ToString(); + string var = vvar.Substring(1,vvar.Length-2).Trim(); + + switch (var.ToLower()) + { + case "%region" : + result = result.Replace(vvar, rs.Region); + break; + case "%host" : + result = result.Replace(vvar, rs.Host); + break; + case "%master1" : + result = result.Replace(vvar, rs.MA1); + break; + case "%master2" : + result = result.Replace(vvar, rs.MA2); + break; + case "%locx" : + result = result.Replace(vvar, rs.LocX); + break; + case "%locy" : + result = result.Replace(vvar, rs.LocY); + break; + case "%k" : + result = result.Replace(vvar, rs.IDK); + break; + default : + result = result.Replace(vvar, rs.config.GetString(var,var)); + break; + } + // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result); + } + + // m_log.DebugFormat("[IRC-Channel] Parse[3]: {0}", result); + return result; + + } + + public void Close() + { + m_log.InfoFormat("[IRC-Channel-{0}] Closing channel <{1}> to server <{2}:{3}>", + idn, IrcChannel, Server, Port); + m_log.InfoFormat("[IRC-Channel-{0}] There are {1} active clients", + idn, clientregions.Count); + irc.Close(); + } + + public void Open() + { + m_log.InfoFormat("[IRC-Channel-{0}] Opening channel <{1}> to server <{2}:{3}>", + idn, IrcChannel, Server, Port); + + irc.Open(); + + } + + // These are called by each region that attaches to this channel. The call affects + // only the relationship of the region with the channel. Not the channel to IRC + // relationship (unless it is closed and we want it open). + + public void Open(RegionState rs) + { + AddRegion(rs); + Open(); + } + + // Close is called to ensure that the IRC session is terminated if this is the + // only client. + + public void Close(RegionState rs) + { + RemoveRegion(rs); + lock (IRCBridgeModule.m_channels) + { + if (clientregions.Count == 0) + { + Close(); + IRCBridgeModule.m_channels.Remove(this); + m_log.InfoFormat("[IRC-Channel-{0}] Region {1} is last user of channel <{2}> to server <{3}:{4}>", + idn, rs.Region, IrcChannel, Server, Port); + m_log.InfoFormat("[IRC-Channel-{0}] Removed", idn); + } + } + } + + // Add a client region to this channel if it is not already known + + public void AddRegion(RegionState rs) + { + m_log.InfoFormat("[IRC-Channel-{0}] Adding region {1} to channel <{2}> to server <{3}:{4}>", + idn, rs.Region, IrcChannel, Server, Port); + if (!clientregions.Contains(rs)) + { + clientregions.Add(rs); + lock (irc) irc.depends++; + } + } + + // Remove a client region from the channel. If this is the last + // region, then clean up the channel. The connector will clean itself + // up if it finds itself about to be GC'd. + + public void RemoveRegion(RegionState rs) + { + + m_log.InfoFormat("[IRC-Channel-{0}] Removing region {1} from channel <{2} to server <{3}:{4}>", + idn, rs.Region, IrcChannel, Server, Port); + + if (clientregions.Contains(rs)) + { + clientregions.Remove(rs); + lock (irc) irc.depends--; + } + + } + + // This function is lifted from the IRCConnector because it + // contains information that is not differentiating from an + // IRC point-of-view. + + public static void OSChat(IRCConnector p_irc, OSChatMessage c, bool cmsg) + { + + // m_log.DebugFormat("[IRC-OSCHAT] from {0}:{1}", p_irc.Server, p_irc.IrcChannel); + + try + { + + // Scan through the set of unique channel configuration for those + // that belong to this connector. And then forward the message to + // all regions known to those channels. + // Note that this code is responsible for completing some of the + // settings for the inbound OSChatMessage + + lock (IRCBridgeModule.m_channels) + { + foreach (ChannelState cs in IRCBridgeModule.m_channels) + { + if ( p_irc == cs.irc) + { + + // This non-IRC differentiator moved to here + + if (cmsg && !cs.ClientReporting) + continue; + + // This non-IRC differentiator moved to here + + c.Channel = (cs.RelayPrivateChannels ? cs.RelayChannel : 0); + + foreach (RegionState region in cs.clientregions) + { + region.OSChat(cs.irc, c); + } + + } + } + } + } + catch (Exception ex) + { + m_log.ErrorFormat("[IRC-OSCHAT]: BroadcastSim Exception: {0}", ex.Message); + m_log.Debug(ex); + } + } + } +} diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs new file mode 100644 index 0000000..0facc14 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs @@ -0,0 +1,219 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Avatar.Chat +{ + public class IRCBridgeModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + internal static bool configured = false; + internal static bool enabled = false; + internal static IConfig m_config = null; + + internal static List m_channels = new List(); + internal static List m_regions = new List(); + + internal static string password = String.Empty; + + internal RegionState region = null; + + #region IRegionModule Members + + public string Name + { + get { return "IRCBridgeModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void Initialise(Scene scene, IConfigSource config) + { + // Do a once-only scan of the configuration file to make + // sure it's basically intact. + + if (!configured) + { + configured = true; + + try + { + if ((m_config = config.Configs["IRC"]) == null) + { + m_log.InfoFormat("[IRC-Bridge] module not configured"); + return; + } + + if (!m_config.GetBoolean("enabled", false)) + { + m_log.InfoFormat("[IRC-Bridge] module disabled in configuration"); + return; + } + } + catch (Exception e) + { + m_log.ErrorFormat("[IRC-Bridge] configuration failed : {0}", e.Message); + return; + } + + enabled = true; + + if (config.Configs["RemoteAdmin"] != null) + { + password = config.Configs["RemoteAdmin"].GetString("access_password", password); + scene.CommsManager.HttpServer.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false); + } + } + + // Iff the IRC bridge is enabled, then each new region may be + // connected to IRC. But it should NOT be obligatory (and it + // is not). + // We have to do ALL of the startup here because PostInitialize + // is not called when a region gets created in-flight from the + // command line. + + if (enabled) + { + try + { + m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName); + region = new RegionState(scene, m_config); + lock (m_regions) m_regions.Add(region); + region.Open(); + } + catch (Exception e) + { + m_log.WarnFormat("[IRC-Bridge] Region {0} not connected to IRC : {1}", scene.RegionInfo.RegionName, e.Message); + m_log.Debug(e); + } + } + else + { + m_log.WarnFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName); + } + } + + // This module can be called in-flight in which case PostInitialize + // is not called following Initialize. So no use is made of this + // call. + + public void PostInitialise() + { + } + + // Called immediately before the region module is unloaded. Cleanup + // the region. + + public void Close() + { + if (!enabled) + return; + + region.Close(); + lock (m_regions) m_regions.Remove(region); + } + + #endregion + + public static XmlRpcResponse XmlRpcAdminMethod(XmlRpcRequest request) + { + m_log.Info("[IRC-Bridge]: XML RPC Admin Entry"); + + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + try + { + Hashtable requestData = (Hashtable)request.Params[0]; + bool found = false; + string region = String.Empty; + + if (password != String.Empty) + { + if (!requestData.ContainsKey("password")) + throw new Exception("Invalid request"); + if ((string)requestData["password"] != password) + throw new Exception("Invalid request"); + } + + if (!requestData.ContainsKey("region")) + throw new Exception("No region name specified"); + region = (string)requestData["region"]; + + foreach (RegionState rs in m_regions) + { + if (rs.Region == region) + { + responseData["server"] = rs.cs.Server; + responseData["port"] = (int)rs.cs.Port; + responseData["user"] = rs.cs.User; + responseData["channel"] = rs.cs.IrcChannel; + responseData["enabled"] = rs.cs.irc.Enabled; + responseData["connected"] = rs.cs.irc.Connected; + responseData["nickname"] = rs.cs.irc.Nick; + found = true; + break; + } + } + + if (!found) throw new Exception(String.Format("Region <{0}> not found", region)); + + responseData["success"] = true; + } + catch (Exception e) + { + m_log.InfoFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message); + + responseData["success"] = "false"; + responseData["error"] = e.Message; + } + finally + { + response.Value = responseData; + } + + m_log.Debug("[IRC-Bridge]: XML RPC Admin Exit"); + + return response; + } + } +} diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs new file mode 100644 index 0000000..f5c324d --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs @@ -0,0 +1,887 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Timers; +using System.Collections.Generic; +using System.IO; +using System.Net.Sockets; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Avatar.Chat +{ + public class IRCConnector + { + + #region Global (static) state + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // Local constants + + private static readonly Vector3 CenterOfRegion = new Vector3(128, 128, 20); + private static readonly char[] CS_SPACE = { ' ' }; + + private const int WD_INTERVAL = 1000; // base watchdog interval + private static int PING_PERIOD = 15; // WD intervals per PING + private static int ICCD_PERIOD = 10; // WD intervals between Connects + private static int L_TIMEOUT = 25; // Login time out interval + + private static int _idk_ = 0; // core connector identifier + private static int _pdk_ = 0; // ping interval counter + private static int _icc_ = 0; // IRC connect counter + + // List of configured connectors + + private static List m_connectors = new List(); + + // Watchdog state + + private static System.Timers.Timer m_watchdog = null; + + static IRCConnector() + { + m_log.DebugFormat("[IRC-Connector]: Static initialization started"); + m_watchdog = new System.Timers.Timer(WD_INTERVAL); + m_watchdog.Elapsed += new ElapsedEventHandler(WatchdogHandler); + m_watchdog.AutoReset = true; + m_watchdog.Start(); + m_log.DebugFormat("[IRC-Connector]: Static initialization complete"); + } + + #endregion + + #region Instance state + + // Connector identity + + internal int idn = _idk_++; + + // How many regions depend upon this connection + // This count is updated by the ChannelState object and reflects the sum + // of the region clients associated with the set of associated channel + // state instances. That's why it cannot be managed here. + + internal int depends = 0; + + // Working threads + + private Thread m_listener = null; + + private Object msyncConnect = new Object(); + + internal bool m_randomizeNick = true; // add random suffix + internal string m_baseNick = null; // base name for randomizing + internal string m_nick = null; // effective nickname + + public string Nick // Public property + { + get { return m_nick; } + set { m_nick = value; } + } + + private bool m_enabled = false; // connector enablement + public bool Enabled + { + get { return m_enabled; } + } + + private bool m_connected = false; // connection status + private bool m_pending = false; // login disposition + private int m_timeout = L_TIMEOUT; // login timeout counter + public bool Connected + { + get { return m_connected; } + } + + private string m_ircChannel; // associated channel id + public string IrcChannel + { + get { return m_ircChannel; } + set { m_ircChannel = value; } + } + + private uint m_port = 6667; // session port + public uint Port + { + get { return m_port; } + set { m_port = value; } + } + + private string m_server = null; // IRC server name + public string Server + { + get { return m_server; } + set { m_server = value; } + } + private string m_password = null; + public string Password + { + get { return m_password; } + set { m_password = value; } + } + + private string m_user = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot"; + public string User + { + get { return m_user; } + } + + // Network interface + + private TcpClient m_tcp; + private NetworkStream m_stream = null; + private StreamReader m_reader; + private StreamWriter m_writer; + + // Channel characteristic info (if available) + + internal string usermod = String.Empty; + internal string chanmod = String.Empty; + internal string version = String.Empty; + internal bool motd = false; + + #endregion + + #region connector instance management + + internal IRCConnector(ChannelState cs) + { + + // Prepare network interface + + m_tcp = null; + m_writer = null; + m_reader = null; + + // Setup IRC session parameters + + m_server = cs.Server; + m_password = cs.Password; + m_baseNick = cs.BaseNickname; + m_randomizeNick = cs.RandomizeNickname; + m_ircChannel = cs.IrcChannel; + m_port = cs.Port; + m_user = cs.User; + + if (m_watchdog == null) + { + // Non-differentiating + + ICCD_PERIOD = cs.ConnectDelay; + PING_PERIOD = cs.PingDelay; + + // Smaller values are not reasonable + + if (ICCD_PERIOD < 5) + ICCD_PERIOD = 5; + + if (PING_PERIOD < 5) + PING_PERIOD = 5; + + _icc_ = ICCD_PERIOD; // get started right away! + + } + + // The last line of defense + + if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) + throw new Exception("Invalid connector configuration"); + + // Generate an initial nickname if randomizing is enabled + + if (m_randomizeNick) + { + m_nick = m_baseNick + Util.RandomClass.Next(1, 99); + } + + // Add the newly created connector to the known connectors list + + m_connectors.Add(this); + + m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); + + } + + ~IRCConnector() + { + m_watchdog.Stop(); + Close(); + } + + // Mark the connector as connectable. Harmless if already enabled. + + public void Open() + { + if (!m_enabled) + { + + m_connectors.Add(this); + m_enabled = true; + + if (!Connected) + { + Connect(); + } + + } + } + + // Only close the connector if the dependency count is zero. + + public void Close() + { + + m_log.InfoFormat("[IRC-Connector-{0}] Closing", idn); + + lock (msyncConnect) + { + + if ((depends == 0) && Enabled) + { + + m_enabled = false; + + if (Connected) + { + m_log.DebugFormat("[IRC-Connector-{0}] Closing interface", idn); + + // Cleanup the IRC session + + try + { + m_writer.WriteLine(String.Format("QUIT :{0} to {1} wormhole to {2} closing", + m_nick, m_ircChannel, m_server)); + m_writer.Flush(); + } + catch (Exception) {} + + + m_connected = false; + + try { m_writer.Close(); } catch (Exception) {} + try { m_reader.Close(); } catch (Exception) {} + try { m_stream.Close(); } catch (Exception) {} + try { m_tcp.Close(); } catch (Exception) {} + + } + + m_connectors.Remove(this); + + } + } + + m_log.InfoFormat("[IRC-Connector-{0}] Closed", idn); + + } + + #endregion + + #region session management + + // Connect to the IRC server. A connector should always be connected, once enabled + + public void Connect() + { + + if (!m_enabled) + return; + + // Delay until next WD cycle if this is too close to the last start attempt + + while (_icc_ < ICCD_PERIOD) + return; + + m_log.DebugFormat("[IRC-Connector-{0}]: Connection request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel); + + lock (msyncConnect) + { + + _icc_ = 0; + + try + { + if (m_connected) return; + + m_connected = true; + m_pending = true; + m_timeout = L_TIMEOUT; + + m_tcp = new TcpClient(m_server, (int)m_port); + m_stream = m_tcp.GetStream(); + m_reader = new StreamReader(m_stream); + m_writer = new StreamWriter(m_stream); + + m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port); + + m_listener = new Thread(new ThreadStart(ListenerRun)); + m_listener.Name = "IRCConnectorListenerThread"; + m_listener.IsBackground = true; + m_listener.Start(); + ThreadTracker.Add(m_listener); + + // This is the message order recommended by RFC 2812 + if (m_password != null) + m_writer.WriteLine(String.Format("PASS {0}", m_password)); + m_writer.WriteLine(String.Format("NICK {0}", m_nick)); + m_writer.Flush(); + m_writer.WriteLine(m_user); + m_writer.Flush(); + m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); + m_writer.Flush(); + + m_log.InfoFormat("[IRC-Connector-{0}]: {1} has asked to join {2}", idn, m_nick, m_ircChannel); + + } + catch (Exception e) + { + m_log.ErrorFormat("[IRC-Connector-{0}] cannot connect {1} to {2}:{3}: {4}", + idn, m_nick, m_server, m_port, e.Message); + m_connected = false; + m_pending = false; + } + + } + + return; + + } + + // Reconnect is used to force a re-cycle of the IRC connection. Should generally + // be a transparent event + + public void Reconnect() + { + m_log.DebugFormat("[IRC-Connector-{0}]: Reconnect request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel); + + // Don't do this if a Connect is in progress... + + lock (msyncConnect) + { + + if (m_connected) + { + m_log.InfoFormat("[IRC-Connector-{0}] Resetting connector", idn); + + // Mark as disconnected. This will allow the listener thread + // to exit if still in-flight. + + + // The listener thread is not aborted - it *might* actually be + // the thread that is running the Reconnect! Instead just close + // the socket and it will disappear of its own accord, once this + // processing is completed. + + try { m_writer.Close(); } catch (Exception) {} + try { m_reader.Close(); } catch (Exception) {} + try { m_tcp.Close(); } catch (Exception) {} + + m_connected = false; + m_pending = false; + + } + + } + + Connect(); + + } + + #endregion + + #region Outbound (to-IRC) message handlers + + public void PrivMsg(string pattern, string from, string region, string msg) + { + + m_log.DebugFormat("[IRC-Connector-{0}] PrivMsg to IRC from {1}: <{2}>", idn, from, + String.Format(pattern, m_ircChannel, from, region, msg)); + + // One message to the IRC server + + try + { + m_writer.WriteLine(pattern, m_ircChannel, from, region, msg); + m_writer.Flush(); + m_log.DebugFormat("[IRC-Connector-{0}]: PrivMsg from {1} in {2}: {3}", idn, from, region, msg); + } + catch (IOException) + { + m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg I/O Error: disconnected from IRC server", idn); + Reconnect(); + } + catch (Exception ex) + { + m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg exception : {1}", idn, ex.Message); + m_log.Debug(ex); + } + + } + + public void Send(string msg) + { + + m_log.DebugFormat("[IRC-Connector-{0}] Send to IRC : <{1}>", idn, msg); + + try + { + m_writer.WriteLine(msg); + m_writer.Flush(); + m_log.DebugFormat("[IRC-Connector-{0}] Sent command string: {1}", idn, msg); + } + catch (IOException) + { + m_log.ErrorFormat("[IRC-Connector-{0}] Disconnected from IRC server.(Send)", idn); + Reconnect(); + } + catch (Exception ex) + { + m_log.ErrorFormat("[IRC-Connector-{0}] Send exception trap: {0}", idn, ex.Message); + m_log.Debug(ex); + } + + } + + #endregion + + public void ListenerRun() + { + string inputLine; + + try + { + while (m_enabled && m_connected) + { + + if ((inputLine = m_reader.ReadLine()) == null) + throw new Exception("Listener input socket closed"); + + // m_log.Info("[IRCConnector]: " + inputLine); + + if (inputLine.Contains("PRIVMSG")) + { + + Dictionary data = ExtractMsg(inputLine); + + // Any chat ??? + if (data != null) + { + + OSChatMessage c = new OSChatMessage(); + c.Message = data["msg"]; + c.Type = ChatTypeEnum.Region; + c.Position = CenterOfRegion; + c.From = data["nick"]; + c.Sender = null; + c.SenderUUID = UUID.Zero; + + // Is message "\001ACTION foo bar\001"? + // Then change to: "/me foo bar" + + if ((1 == c.Message[0]) && c.Message.Substring(1).StartsWith("ACTION")) + c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9)); + + ChannelState.OSChat(this, c, false); + + } + + } + else + { + ProcessIRCCommand(inputLine); + } + } + } + catch (Exception /*e*/) + { + // m_log.ErrorFormat("[IRC-Connector-{0}]: ListenerRun exception trap: {1}", idn, e.Message); + // m_log.Debug(e); + } + + // This is potentially circular, but harmless if so. + // The connection is marked as not connected the first time + // through reconnect. + + if (m_enabled) Reconnect(); + + } + + private Regex RE = new Regex(@":(?[\w-]*)!(?\S*) PRIVMSG (?\S+) :(?.*)", + RegexOptions.Multiline); + + private Dictionary ExtractMsg(string input) + { + //examines IRC commands and extracts any private messages + // which will then be reboadcast in the Sim + + // m_log.InfoFormat("[IRC-Connector-{0}]: ExtractMsg: {1}", idn, input); + + Dictionary result = null; + MatchCollection matches = RE.Matches(input); + + // Get some direct matches $1 $4 is a + if ((matches.Count == 0) || (matches.Count != 1) || (matches[0].Groups.Count != 5)) + { + // m_log.Info("[IRCConnector]: Number of matches: " + matches.Count); + // if (matches.Count > 0) + // { + // m_log.Info("[IRCConnector]: Number of groups: " + matches[0].Groups.Count); + // } + return null; + } + + result = new Dictionary(); + result.Add("nick", matches[0].Groups[1].Value); + result.Add("user", matches[0].Groups[2].Value); + result.Add("channel", matches[0].Groups[3].Value); + result.Add("msg", matches[0].Groups[4].Value); + + return result; + } + + public void BroadcastSim(string sender, string format, params string[] args) + { + try + { + OSChatMessage c = new OSChatMessage(); + c.From = sender; + c.Message = String.Format(format, args); + c.Type = ChatTypeEnum.Region; // ChatTypeEnum.Say; + c.Position = CenterOfRegion; + c.Sender = null; + c.SenderUUID = UUID.Zero; + + ChannelState.OSChat(this, c, true); + + } + catch (Exception ex) // IRC gate should not crash Sim + { + m_log.ErrorFormat("[IRC-Connector-{0}]: BroadcastSim Exception Trap: {1}\n{2}", idn, ex.Message, ex.StackTrace); + } + } + + #region IRC Command Handlers + + public void ProcessIRCCommand(string command) + { + + string[] commArgs; + string c_server = m_server; + + string pfx = String.Empty; + string cmd = String.Empty; + string parms = String.Empty; + + // ":" indicates that a prefix is present + // There are NEVER more than 17 real + // fields. A parameter that starts with + // ":" indicates that the remainder of the + // line is a single parameter value. + + commArgs = command.Split(CS_SPACE,2); + + if (commArgs[0].StartsWith(":")) + { + pfx = commArgs[0].Substring(1); + commArgs = commArgs[1].Split(CS_SPACE,2); + } + + cmd = commArgs[0]; + parms = commArgs[1]; + + // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd); + + switch (cmd) + { + + // Messages 001-004 are always sent + // following signon. + + case "001" : // Welcome ... + case "002" : // Server information + case "003" : // Welcome ... + break; + case "004" : // Server information + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + commArgs = parms.Split(CS_SPACE); + c_server = commArgs[1]; + m_server = c_server; + version = commArgs[2]; + usermod = commArgs[3]; + chanmod = commArgs[4]; + break; + case "005" : // Server information + break; + case "042" : + case "250" : + case "251" : + case "252" : + case "254" : + case "255" : + case "265" : + case "266" : + case "332" : // Subject + case "333" : // Subject owner (?) + case "353" : // Name list + case "366" : // End-of-Name list marker + case "372" : // MOTD body + case "375" : // MOTD start + m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); + break; + case "376" : // MOTD end + m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); + motd = true; + break; + case "451" : // Not registered + break; + case "433" : // Nickname in use + // Gen a new name + m_nick = m_baseNick + Util.RandomClass.Next(1, 99); + m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick); + // Retry + m_writer.WriteLine(String.Format("NICK {0}", m_nick)); + m_writer.Flush(); + m_writer.WriteLine(m_user); + m_writer.Flush(); + m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); + m_writer.Flush(); + break; + case "479" : // Bad channel name, etc. This will never work, so disable the connection + m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); + m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd); + m_enabled = false; + m_connected = false; + m_pending = false; + break; + case "NOTICE" : + m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); + break; + case "ERROR" : + m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); + if (parms.Contains("reconnect too fast")) + ICCD_PERIOD++; + m_pending = false; + Reconnect(); + break; + case "PING" : + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + m_writer.WriteLine(String.Format("PONG {0}", parms)); + m_writer.Flush(); + break; + case "PONG" : + break; + case "JOIN": + if (m_pending) + { + m_log.InfoFormat("[IRC-Connector-{0}] [{1}] Connected", idn, cmd); + m_pending = false; + } + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + eventIrcJoin(pfx, cmd, parms); + break; + case "PART": + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + eventIrcPart(pfx, cmd, parms); + break; + case "MODE": + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + eventIrcMode(pfx, cmd, parms); + break; + case "NICK": + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + eventIrcNickChange(pfx, cmd, parms); + break; + case "KICK": + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + eventIrcKick(pfx, cmd, parms); + break; + case "QUIT": + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); + eventIrcQuit(pfx, cmd, parms); + break; + default : + m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms); + break; + } + + // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd); + + } + + public void eventIrcJoin(string prefix, string command, string parms) + { + string[] args = parms.Split(CS_SPACE,2); + string IrcUser = prefix.Split('!')[0]; + string IrcChannel = args[0]; + + if (IrcChannel.StartsWith(":")) + IrcChannel = IrcChannel.Substring(1); + + m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCJoin {1}:{2}", idn, m_server, m_ircChannel); + BroadcastSim(IrcUser, "/me joins {0}", IrcChannel); + } + + public void eventIrcPart(string prefix, string command, string parms) + { + string[] args = parms.Split(CS_SPACE,2); + string IrcUser = prefix.Split('!')[0]; + string IrcChannel = args[0]; + + m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel); + BroadcastSim(IrcUser, "/me parts {0}", IrcChannel); + } + + public void eventIrcMode(string prefix, string command, string parms) + { + string[] args = parms.Split(CS_SPACE,2); + string UserMode = args[1]; + + m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel); + if (UserMode.Substring(0, 1) == ":") + { + UserMode = UserMode.Remove(0, 1); + } + } + + public void eventIrcNickChange(string prefix, string command, string parms) + { + string[] args = parms.Split(CS_SPACE,2); + string UserOldNick = prefix.Split('!')[0]; + string UserNewNick = args[0].Remove(0, 1); + + m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCNickChange {1}:{2}", idn, m_server, m_ircChannel); + BroadcastSim(UserOldNick, "/me is now known as {0}", UserNewNick); + } + + public void eventIrcKick(string prefix, string command, string parms) + { + string[] args = parms.Split(CS_SPACE,3); + string UserKicker = prefix.Split('!')[0]; + string IrcChannel = args[0]; + string UserKicked = args[1]; + string KickMessage = args[2]; + + m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel); + BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage); + + if (UserKicked == m_nick) + { + BroadcastSim(m_nick, "Hey, that was me!!!"); + } + + } + + public void eventIrcQuit(string prefix, string command, string parms) + { + string IrcUser = prefix.Split('!')[0]; + string QuitMessage = parms; + + m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel); + BroadcastSim(IrcUser, "/me quits saying \"{0}\"", QuitMessage); + } + + #endregion + + #region Connector Watch Dog + + // A single watch dog monitors extant connectors and makes sure that they + // are re-connected as necessary. If a connector IS connected, then it is + // pinged, but only if a PING period has elapsed. + + protected static void WatchdogHandler(Object source, ElapsedEventArgs args) + { + + // m_log.InfoFormat("[IRC-Watchdog] Status scan"); + + _pdk_ = (_pdk_+1)%PING_PERIOD; // cycle the ping trigger + _icc_++; // increment the inter-consecutive-connect-delay counter + + foreach (IRCConnector connector in m_connectors) + { + if (connector.Enabled) + { + if (!connector.Connected) + { + try + { + // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel); + connector.Connect(); + } + catch (Exception e) + { + m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message); + } + } + else + { + + if (connector.m_pending) + { + if (connector.m_timeout == 0) + { + m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn); + connector.Reconnect(); + } + else + connector.m_timeout--; + } + + if (_pdk_ == 0) + { + try + { + connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server)); + connector.m_writer.Flush(); + } + catch (Exception /*e*/) + { + // m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message); + // m_log.Debug(e); + connector.Reconnect(); + } + } + + } + } + } + + // m_log.InfoFormat("[IRC-Watchdog] Status scan completed"); + + } + + #endregion + + } +} diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs new file mode 100644 index 0000000..6733120 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs @@ -0,0 +1,424 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text.RegularExpressions; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Avatar.Chat +{ + // An instance of this class exists for every active region + + internal class RegionState + { + + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(128, 128, 20); + private const int DEBUG_CHANNEL = 2147483647; + + private static int _idk_ = 0; + + // Runtime variables; these values are assigned when the + // IrcState is created and remain constant thereafter. + + internal string Region = String.Empty; + internal string Host = String.Empty; + internal string LocX = String.Empty; + internal string LocY = String.Empty; + internal string MA1 = String.Empty; + internal string MA2 = String.Empty; + internal string IDK = String.Empty; + + // System values - used only be the IRC classes themselves + + internal ChannelState cs = null; // associated IRC configuration + internal Scene scene = null; // associated scene + internal IConfig config = null; // configuration file reference + internal bool enabled = true; + + // This list is used to keep track of who is here, and by + // implication, who is not. + + internal List clients = new List(); + + // Setup runtime variable values + + public RegionState(Scene p_scene, IConfig p_config) + { + + scene = p_scene; + config = p_config; + + Region = scene.RegionInfo.RegionName; + Host = scene.RegionInfo.ExternalHostName; + LocX = Convert.ToString(scene.RegionInfo.RegionLocX); + LocY = Convert.ToString(scene.RegionInfo.RegionLocY); + MA1 = scene.RegionInfo.MasterAvatarFirstName; + MA2 = scene.RegionInfo.MasterAvatarLastName; + IDK = Convert.ToString(_idk_++); + + // OpenChannel conditionally establishes a connection to the + // IRC server. The request will either succeed, or it will + // throw an exception. + + ChannelState.OpenChannel(this, config); + + // Connect channel to world events + + scene.EventManager.OnChatFromWorld += OnSimChat; + scene.EventManager.OnChatFromClient += OnSimChat; + scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; + scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; + + m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region); + + } + + // Auto cleanup when abandoned + + ~RegionState() + { + if (cs != null) + cs.RemoveRegion(this); + } + + // Called by PostInitialize after all regions have been created + + public void Open() + { + cs.Open(this); + enabled = true; + } + + // Called by IRCBridgeModule.Close immediately prior to unload + // of the module for this region. This happens when the region + // is being removed or the server is terminating. The IRC + // BridgeModule will remove the region from the region list + // when control returns. + + public void Close() + { + enabled = false; + cs.Close(this); + } + + // The agent has disconnected, cleanup associated resources + + private void OnClientLoggedOut(IClientAPI client) + { + try + { + if (clients.Contains(client)) + { + if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) + { + m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name); + cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name)); + } + client.OnLogout -= OnClientLoggedOut; + client.OnConnectionClosed -= OnClientLoggedOut; + clients.Remove(client); + } + } + catch (Exception ex) + { + m_log.ErrorFormat("[IRC-Region {0}]: ClientLoggedOut exception: {1}", Region, ex.Message); + m_log.Debug(ex); + } + } + + // This event indicates that the agent has left the building. We should treat that the same + // as if the agent has logged out (we don't want cross-region noise - or do we?) + + private void OnMakeChildAgent(ScenePresence presence) + { + + IClientAPI client = presence.ControllingClient; + + try + { + if (clients.Contains(client)) + { + if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) + { + string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); + m_log.DebugFormat("[IRC-Region {0}] {1} has left", Region, clientName); + cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", clientName)); + } + client.OnLogout -= OnClientLoggedOut; + client.OnConnectionClosed -= OnClientLoggedOut; + clients.Remove(client); + } + } + catch (Exception ex) + { + m_log.ErrorFormat("[IRC-Region {0}]: MakeChildAgent exception: {1}", Region, ex.Message); + m_log.Debug(ex); + } + + } + + // An agent has entered the region (from another region). Add the client to the locally + // known clients list + + private void OnMakeRootAgent(ScenePresence presence) + { + + IClientAPI client = presence.ControllingClient; + + try + { + if (!clients.Contains(client)) + { + client.OnLogout += OnClientLoggedOut; + client.OnConnectionClosed += OnClientLoggedOut; + clients.Add(client); + if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) + { + string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); + m_log.DebugFormat("[IRC-Region {0}] {1} has arrived", Region, clientName); + cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has arrived", clientName)); + } + } + } + catch (Exception ex) + { + m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message); + m_log.Debug(ex); + } + + } + + // This handler detects chat events int he virtual world. + + public void OnSimChat(Object sender, OSChatMessage msg) + { + + // early return if this comes from the IRC forwarder + + if (cs.irc.Equals(sender)) return; + + // early return if nothing to forward + + if (msg.Message.Length == 0) return; + + // check for commands coming from avatars or in-world + // object (if commands are enabled) + + if (cs.CommandsEnabled && msg.Channel == cs.CommandChannel) + { + + m_log.DebugFormat("[IRC-Region {0}] command on channel {1}: {2}", Region, msg.Channel, msg.Message); + + string[] messages = msg.Message.Split(' '); + string command = messages[0].ToLower(); + + try + { + switch (command) + { + + // These commands potentially require a change in the + // underlying ChannelState. + + case "server": + cs.Close(this); + cs = cs.UpdateServer(this, messages[1]); + cs.Open(this); + break; + case "port": + cs.Close(this); + cs = cs.UpdatePort(this, messages[1]); + cs.Open(this); + break; + case "channel": + cs.Close(this); + cs = cs.UpdateChannel(this, messages[1]); + cs.Open(this); + break; + case "nick": + cs.Close(this); + cs = cs.UpdateNickname(this, messages[1]); + cs.Open(this); + break; + + // These may also (but are less likely) to require a + // change in ChannelState. + + case "client-reporting": + cs = cs.UpdateClientReporting(this, messages[1]); + break; + case "in-channel": + cs = cs.UpdateRelayIn(this, messages[1]); + break; + case "out-channel": + cs = cs.UpdateRelayOut(this, messages[1]); + break; + + // These are all taken to be temporary changes in state + // so the underlying connector remains intact. But note + // that with regions sharing a connector, there could + // be interference. + + case "close": + enabled = false; + cs.Close(this); + break; + + case "connect": + enabled = true; + cs.Open(this); + break; + + case "reconnect": + enabled = true; + cs.Close(this); + cs.Open(this); + break; + + // This one is harmless as far as we can judge from here. + // If it is not, then the complaints will eventually make + // that evident. + + default: + m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}", + Region, msg.Message); + cs.irc.Send(msg.Message); + break; + } + } + catch (Exception ex) + { + m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}", + Region, ex.Message); + m_log.Debug(ex); + } + + return; + + } + + // The command channel remains enabled, even if we have otherwise disabled the IRC + // interface. + + if (!enabled) + return; + + // drop messages unless they are on a valid in-world + // channel as configured in the ChannelState + + if (!cs.ValidInWorldChannels.Contains(msg.Channel)) + { + m_log.DebugFormat("[IRC-Region {0}] dropping message {1} on channel {2}", Region, msg, msg.Channel); + return; + } + + ScenePresence avatar = null; + string fromName = msg.From; + + if (msg.Sender != null) + { + avatar = scene.GetScenePresence(msg.Sender.AgentId); + if (avatar != null) fromName = avatar.Name; + } + + if (!cs.irc.Connected) + { + m_log.WarnFormat("[IRC-Region {0}] IRCConnector not connected: dropping message from {1}", Region, fromName); + return; + } + + m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message); + + if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL)) + { + string txt = msg.Message; + if (txt.StartsWith("/me ")) + txt = String.Format("{0} {1}", fromName, msg.Message.Substring(4)); + + cs.irc.PrivMsg(cs.PrivateMessageFormat, fromName, Region, txt); + return; + } + + if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword && + msg.Channel == cs.RelayChannelOut) + { + Match m = cs.AccessPasswordRegex.Match(msg.Message); + if (null != m) + { + m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(), + m.Groups["message"].ToString()); + cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(), + scene.RegionInfo.RegionName, m.Groups["message"].ToString()); + } + } + } + + // This method gives the region an opportunity to interfere with + // message delivery. For now we just enforce the enable/disable + // flag. + + internal void OSChat(Object irc, OSChatMessage msg) + { + if (enabled) + { + // m_log.DebugFormat("[IRC-OSCHAT] Region {0} being sent message", region.Region); + msg.Scene = scene; + scene.EventManager.TriggerOnChatBroadcast(irc, msg); + } + } + + // This supports any local message traffic that might be needed in + // support of command processing. At present there is none. + + internal void LocalChat(string msg) + { + if (enabled) + { + OSChatMessage osm = new OSChatMessage(); + osm.From = "IRC Agent"; + osm.Message = msg; + osm.Type = ChatTypeEnum.Region; + osm.Position = CenterOfRegion; + osm.Sender = null; + osm.SenderUUID = OpenMetaverse.UUID.Zero; // Hmph! Still? + osm.Channel = 0; + OSChat(this, osm); + } + } + + } + +} diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs new file mode 100644 index 0000000..bb46b11 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -0,0 +1,604 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.Avatar.Chat; + +namespace OpenSim.Region.OptionalModules.Avatar.Concierge +{ + public class ConciergeModule : ChatModule, IRegionModule + { + private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const int DEBUG_CHANNEL = 2147483647; + + private List _scenes = new List(); + private List _conciergedScenes = new List(); + private Dictionary> _sceneAttendees = + new Dictionary>(); + private Dictionary _attendeeNames = + new Dictionary(); + + private bool _replacingChatModule = false; + + private IConfig _config; + + private string _whoami = "conferencier"; + private Regex _regions = null; + private string _welcomes = null; + private int _conciergeChannel = 42; + private string _announceEntering = "{0} enters {1} (now {2} visitors in this region)"; + private string _announceLeaving = "{0} leaves {1} (back to {2} visitors in this region)"; + private string _xmlRpcPassword = String.Empty; + private string _brokerURI = String.Empty; + + internal object _syncy = new object(); + + #region IRegionModule Members + public override void Initialise(Scene scene, IConfigSource config) + { + try + { + if ((_config = config.Configs["Concierge"]) == null) + { + //_log.InfoFormat("[Concierge]: no configuration section [Concierge] in OpenSim.ini: module not configured"); + return; + } + + if (!_config.GetBoolean("enabled", false)) + { + //_log.InfoFormat("[Concierge]: module disabled by OpenSim.ini configuration"); + return; + } + } + catch (Exception) + { + _log.Info("[Concierge]: module not configured"); + return; + } + + // check whether ChatModule has been disabled: if yes, + // then we'll "stand in" + try + { + if (config.Configs["Chat"] == null) + { + _replacingChatModule = false; + } + else + { + _replacingChatModule = !config.Configs["Chat"].GetBoolean("enabled", true); + } + } + catch (Exception) + { + _replacingChatModule = false; + } + _log.InfoFormat("[Concierge] {0} ChatModule", _replacingChatModule ? "replacing" : "not replacing"); + + + // take note of concierge channel and of identity + _conciergeChannel = config.Configs["Concierge"].GetInt("concierge_channel", _conciergeChannel); + _whoami = _config.GetString("whoami", "conferencier"); + _welcomes = _config.GetString("welcomes", _welcomes); + _announceEntering = _config.GetString("announce_entering", _announceEntering); + _announceLeaving = _config.GetString("announce_leaving", _announceLeaving); + _xmlRpcPassword = _config.GetString("password", _xmlRpcPassword); + _brokerURI = _config.GetString("broker", _brokerURI); + + _log.InfoFormat("[Concierge] reporting as \"{0}\" to our users", _whoami); + + // calculate regions Regex + if (_regions == null) + { + string regions = _config.GetString("regions", String.Empty); + if (!String.IsNullOrEmpty(regions)) + { + _regions = new Regex(@regions, RegexOptions.Compiled | RegexOptions.IgnoreCase); + } + } + + scene.CommsManager.HttpServer.AddXmlRPCHandler("concierge_update_welcome", XmlRpcUpdateWelcomeMethod, false); + + lock (_syncy) + { + if (!_scenes.Contains(scene)) + { + _scenes.Add(scene); + + if (_regions == null || _regions.IsMatch(scene.RegionInfo.RegionName)) + _conciergedScenes.Add(scene); + + // subscribe to NewClient events + scene.EventManager.OnNewClient += OnNewClient; + + // subscribe to *Chat events + scene.EventManager.OnChatFromWorld += OnChatFromWorld; + if (!_replacingChatModule) + scene.EventManager.OnChatFromClient += OnChatFromClient; + scene.EventManager.OnChatBroadcast += OnChatBroadcast; + + // subscribe to agent change events + scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; + scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; + } + } + _log.InfoFormat("[Concierge]: initialized for {0}", scene.RegionInfo.RegionName); + } + + public override void PostInitialise() + { + } + + public override void Close() + { + } + + public override string Name + { + get { return "ConciergeModule"; } + } + + public override bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region ISimChat Members + public override void OnChatBroadcast(Object sender, OSChatMessage c) + { + if (_replacingChatModule) + { + // distribute chat message to each and every avatar in + // the region + base.OnChatBroadcast(sender, c); + } + + // TODO: capture logic + return; + } + + public override void OnChatFromClient(Object sender, OSChatMessage c) + { + if (_replacingChatModule) + { + // replacing ChatModule: need to redistribute + // ChatFromClient to interested subscribers + c = FixPositionOfChatMessage(c); + + Scene scene = (Scene)c.Scene; + scene.EventManager.TriggerOnChatFromClient(sender, c); + + if (_conciergedScenes.Contains(c.Scene)) + { + // when we are replacing ChatModule, we treat + // OnChatFromClient like OnChatBroadcast for + // concierged regions, effectively extending the + // range of chat to cover the whole + // region. however, we don't do this for whisper + // (got to have some privacy) + if (c.Type != ChatTypeEnum.Whisper) + { + base.OnChatBroadcast(sender, c); + return; + } + } + + // redistribution will be done by base class + base.OnChatFromClient(sender, c); + } + + // TODO: capture chat + return; + } + + public override void OnChatFromWorld(Object sender, OSChatMessage c) + { + if (_replacingChatModule) + { + if (_conciergedScenes.Contains(c.Scene)) + { + // when we are replacing ChatModule, we treat + // OnChatFromClient like OnChatBroadcast for + // concierged regions, effectively extending the + // range of chat to cover the whole + // region. however, we don't do this for whisper + // (got to have some privacy) + if (c.Type != ChatTypeEnum.Whisper) + { + base.OnChatBroadcast(sender, c); + return; + } + } + + base.OnChatFromWorld(sender, c); + } + return; + } + #endregion + + + public override void OnNewClient(IClientAPI client) + { + client.OnLogout += OnClientLoggedOut; + + if (_replacingChatModule) + client.OnChatFromClient += OnChatFromClient; + } + + + + public void OnClientLoggedOut(IClientAPI client) + { + client.OnLogout -= OnClientLoggedOut; + client.OnConnectionClosed -= OnClientLoggedOut; + + if (_conciergedScenes.Contains(client.Scene)) + { + _log.DebugFormat("[Concierge]: {0} logs off from {1}", client.Name, client.Scene.RegionInfo.RegionName); + RemoveFromAttendeeList(client.AgentId, client.Name, client.Scene); + AnnounceToAgentsRegion(client.Scene, String.Format(_announceLeaving, client.Name, client.Scene.RegionInfo.RegionName, + _sceneAttendees[client.Scene].Count)); + UpdateBroker(client.Scene); + } + } + + + public void OnMakeRootAgent(ScenePresence agent) + { + if (_conciergedScenes.Contains(agent.Scene)) + { + _log.DebugFormat("[Concierge]: {0} enters {1}", agent.Name, agent.Scene.RegionInfo.RegionName); + AddToAttendeeList(agent.UUID, agent.Name, agent.Scene); + WelcomeAvatar(agent, agent.Scene); + AnnounceToAgentsRegion(agent.Scene, String.Format(_announceEntering, agent.Name, agent.Scene.RegionInfo.RegionName, + _sceneAttendees[agent.Scene].Count)); + UpdateBroker(agent.Scene); + } + } + + + public void OnMakeChildAgent(ScenePresence agent) + { + if (_conciergedScenes.Contains(agent.Scene)) + { + _log.DebugFormat("[Concierge]: {0} leaves {1}", agent.Name, agent.Scene.RegionInfo.RegionName); + RemoveFromAttendeeList(agent.UUID, agent.Name, agent.Scene); + AnnounceToAgentsRegion(agent.Scene, String.Format(_announceLeaving, agent.Name, agent.Scene.RegionInfo.RegionName, + _sceneAttendees[agent.Scene].Count)); + UpdateBroker(agent.Scene); + } + } + + protected void AddToAttendeeList(UUID agentID, string name, Scene scene) + { + lock (_sceneAttendees) + { + if (!_sceneAttendees.ContainsKey(scene)) + _sceneAttendees[scene] = new List(); + + List attendees = _sceneAttendees[scene]; + if (!attendees.Contains(agentID)) + { + attendees.Add(agentID); + _attendeeNames[agentID] = name; + } + } + } + + protected void RemoveFromAttendeeList(UUID agentID, String name, IScene scene) + { + lock (_sceneAttendees) + { + if (!_sceneAttendees.ContainsKey(scene)) + { + _log.WarnFormat("[Concierge]: attendee list missing for region {0}", scene.RegionInfo.RegionName); + return; + } + + List attendees = _sceneAttendees[scene]; + if (!attendees.Contains(agentID)) + { + _log.WarnFormat("[Concierge]: avatar {0} must have sneaked in to region {1} earlier", + name, scene.RegionInfo.RegionName); + return; + } + + attendees.Remove(agentID); + _attendeeNames.Remove(agentID); + } + } + + protected void UpdateBroker(IScene scene) + { + if (String.IsNullOrEmpty(_brokerURI)) + return; + + string uri = String.Format(_brokerURI, scene.RegionInfo.RegionName, scene.RegionInfo.RegionID); + + // get attendee list for the scene + List attendees; + lock (_sceneAttendees) + { + if (!_sceneAttendees.ContainsKey(scene)) + { + _log.DebugFormat("[Concierge]: attendee list missing for region {0}", scene.RegionInfo.RegionName); + return; + } + + attendees = _sceneAttendees[scene]; + } + + // create XML sniplet + StringBuilder list = new StringBuilder(); + if (0 == attendees.Count) + { + list.Append(String.Format("", + scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, + DateTime.UtcNow.ToString("s"))); + } + else + { + list.Append(String.Format("\n", + attendees.Count, scene.RegionInfo.RegionName, + scene.RegionInfo.RegionID, + DateTime.UtcNow.ToString("s"))); + foreach (UUID uuid in attendees) + { + string name = _attendeeNames[uuid]; + list.Append(String.Format(" \n", name, uuid)); + } + list.Append(""); + } + string payload = list.ToString(); + + // post via REST to broker + HttpWebRequest updatePost = WebRequest.Create(uri) as HttpWebRequest; + updatePost.Method = "POST"; + updatePost.ContentType = "text/xml"; + updatePost.ContentLength = payload.Length; + updatePost.UserAgent = "OpenSim.Concierge"; + + try + { + StreamWriter payloadStream = new StreamWriter(updatePost.GetRequestStream()); + payloadStream.Write(payload); + payloadStream.Close(); + + updatePost.BeginGetResponse(UpdateBrokerDone, updatePost); + _log.DebugFormat("[Concierge] async broker POST to {0} started", uri); + } + catch (WebException we) + { + _log.ErrorFormat("[Concierge] async broker POST to {0} failed: {1}", uri, we.Status); + } + } + + private void UpdateBrokerDone(IAsyncResult result) + { + HttpWebRequest updatePost = null; + try + { + updatePost = result.AsyncState as HttpWebRequest; + using (HttpWebResponse response = updatePost.EndGetResponse(result) as HttpWebResponse) + { + _log.DebugFormat("[Concierge] broker update: status {0}", response.StatusCode); + } + } + catch (WebException we) + { + string uri = updatePost.RequestUri.OriginalString; + _log.ErrorFormat("[Concierge] broker update to {0} failed with status {1}", uri, we.Status); + if (null != we.Response) + { + using (HttpWebResponse resp = we.Response as HttpWebResponse) + { + _log.ErrorFormat("[Concierge] response from {0} status code: {1}", uri, resp.StatusCode); + _log.ErrorFormat("[Concierge] response from {0} status desc: {1}", uri, resp.StatusDescription); + _log.ErrorFormat("[Concierge] response from {0} server: {1}", uri, resp.Server); + + if (resp.ContentLength > 0) + { + StreamReader content = new StreamReader(resp.GetResponseStream()); + _log.ErrorFormat("[Concierge] response from {0} content: {1}", uri, content.ReadToEnd()); + content.Close(); + } + } + } + } + } + + protected void WelcomeAvatar(ScenePresence agent, Scene scene) + { + // welcome mechanics: check whether we have a welcomes + // directory set and wether there is a region specific + // welcome file there: if yes, send it to the agent + if (!String.IsNullOrEmpty(_welcomes)) + { + string[] welcomes = new string[] { + Path.Combine(_welcomes, agent.Scene.RegionInfo.RegionName), + Path.Combine(_welcomes, "DEFAULT")}; + foreach (string welcome in welcomes) + { + if (File.Exists(welcome)) + { + try + { + string[] welcomeLines = File.ReadAllLines(welcome); + foreach (string l in welcomeLines) + { + AnnounceToAgent(agent, String.Format(l, agent.Name, scene.RegionInfo.RegionName, _whoami)); + } + } + catch (IOException ioe) + { + _log.ErrorFormat("[Concierge]: run into trouble reading welcome file {0} for region {1} for avatar {2}: {3}", + welcome, scene.RegionInfo.RegionName, agent.Name, ioe); + } + catch (FormatException fe) + { + _log.ErrorFormat("[Concierge]: welcome file {0} is malformed: {1}", welcome, fe); + } + } + return; + } + _log.DebugFormat("[Concierge]: no welcome message for region {0}", scene.RegionInfo.RegionName); + } + } + + static private Vector3 PosOfGod = new Vector3(128, 128, 9999); + + // protected void AnnounceToAgentsRegion(Scene scene, string msg) + // { + // ScenePresence agent = null; + // if ((client.Scene is Scene) && (client.Scene as Scene).TryGetAvatar(client.AgentId, out agent)) + // AnnounceToAgentsRegion(agent, msg); + // else + // _log.DebugFormat("[Concierge]: could not find an agent for client {0}", client.Name); + // } + + protected void AnnounceToAgentsRegion(IScene scene, string msg) + { + OSChatMessage c = new OSChatMessage(); + c.Message = msg; + c.Type = ChatTypeEnum.Say; + c.Channel = 0; + c.Position = PosOfGod; + c.From = _whoami; + c.Sender = null; + c.SenderUUID = UUID.Zero; + c.Scene = scene; + + if (scene is Scene) + (scene as Scene).EventManager.TriggerOnChatBroadcast(this, c); + } + + protected void AnnounceToAgent(ScenePresence agent, string msg) + { + OSChatMessage c = new OSChatMessage(); + c.Message = msg; + c.Type = ChatTypeEnum.Say; + c.Channel = 0; + c.Position = PosOfGod; + c.From = _whoami; + c.Sender = null; + c.SenderUUID = UUID.Zero; + c.Scene = agent.Scene; + + agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, _whoami, UUID.Zero, + (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); + } + + private static void checkStringParameters(XmlRpcRequest request, string[] param) + { + Hashtable requestData = (Hashtable) request.Params[0]; + foreach (string p in param) + { + if (!requestData.Contains(p)) + throw new Exception(String.Format("missing string parameter {0}", p)); + if (String.IsNullOrEmpty((string)requestData[p])) + throw new Exception(String.Format("parameter {0} is empty", p)); + } + } + + public XmlRpcResponse XmlRpcUpdateWelcomeMethod(XmlRpcRequest request) + { + _log.Info("[Concierge]: processing UpdateWelcome request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + try + { + Hashtable requestData = (Hashtable)request.Params[0]; + checkStringParameters(request, new string[] { "password", "region", "welcome" }); + + // check password + if (!String.IsNullOrEmpty(_xmlRpcPassword) && + (string)requestData["password"] != _xmlRpcPassword) throw new Exception("wrong password"); + + if (String.IsNullOrEmpty(_welcomes)) + throw new Exception("welcome templates are not enabled, ask your OpenSim operator to set the \"welcomes\" option in the [Concierge] section of OpenSim.ini"); + + string msg = (string)requestData["welcome"]; + if (String.IsNullOrEmpty(msg)) + throw new Exception("empty parameter \"welcome\""); + + string regionName = (string)requestData["region"]; + IScene scene = _scenes.Find(delegate(IScene s) { return s.RegionInfo.RegionName == regionName; }); + if (scene == null) + throw new Exception(String.Format("unknown region \"{0}\"", regionName)); + + if (!_conciergedScenes.Contains(scene)) + throw new Exception(String.Format("region \"{0}\" is not a concierged region.", regionName)); + + string welcome = Path.Combine(_welcomes, regionName); + if (File.Exists(welcome)) + { + _log.InfoFormat("[Concierge]: UpdateWelcome: updating existing template \"{0}\"", welcome); + string welcomeBackup = String.Format("{0}~", welcome); + if (File.Exists(welcomeBackup)) + File.Delete(welcomeBackup); + File.Move(welcome, welcomeBackup); + } + File.WriteAllText(welcome, msg); + + responseData["success"] = "true"; + response.Value = responseData; + } + catch (Exception e) + { + _log.InfoFormat("[Concierge]: UpdateWelcome failed: {0}", e.Message); + + responseData["success"] = "false"; + responseData["error"] = e.Message; + + response.Value = responseData; + } + _log.Debug("[Concierge]: done processing UpdateWelcome request"); + return response; + } + } +} diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeServer.py b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeServer.py new file mode 100755 index 0000000..1c088fb --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeServer.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# +# Copyright (c) Contributors, http://opensimulator.org/ +# See CONTRIBUTORS.TXT for a full list of copyright holders. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the OpenSim Project nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +import logging +import BaseHTTPServer +import optparse +import xml.etree.ElementTree as ET +import xml.parsers.expat + + +# enable debug level logging +logging.basicConfig(level = logging.DEBUG, + format='%(asctime)s %(levelname)s %(message)s') + +options = None + +# subclassed HTTPRequestHandler +class ConciergeHandler(BaseHTTPServer.BaseHTTPRequestHandler): + def logRequest(self): + logging.info('[ConciergeHandler] %(command)s request: %(host)s:%(port)d --- %(path)s', + dict(command = self.command, + host = self.client_address[0], + port = self.client_address[1], + path = self.path)) + + def logResponse(self, status): + logging.info('[ConciergeHandler] %(command)s returned %(status)d', + dict(command = self.command, + status = status)) + + + def do_HEAD(self): + self.logRequest() + + self.send_response(200) + self.send_header('Content-type', 'text/html') + self.end_headers() + + self.logResponse(200) + + def dumpXml(self, xml): + logging.debug('[ConciergeHandler] %s', xml.tag) + for attr in xml.attrib: + logging.debug('[ConciergeHandler] %s [%s] %s', xml.tag, attr, xml.attrib[attr]) + for kid in xml.getchildren(): + self.dumpXml(kid) + + def do_POST(self): + self.logRequest() + hdrs = {} + for hdr in self.headers.headers: + logging.debug('[ConciergeHandler] POST: header: %s', hdr.rstrip()) + + length = int(self.headers.getheader('Content-Length')) + content = self.rfile.read(length) + self.rfile.close() + + logging.debug('[ConciergeHandler] POST: content: %s', content) + try: + postXml = ET.fromstring(content) + self.dumpXml(postXml) + except xml.parsers.expat.ExpatError, xmlError: + logging.error('[ConciergeHandler] POST illformed:%s', xmlError) + self.send_response(500) + return + + if not options.fail: + self.send_response(200) + self.send_header('Content-Type', 'text/html') + self.send_header('Content-Length', len('')) + self.end_headers() + self.logResponse(200) + self.wfile.write('') + self.wfile.close() + else: + self.send_response(500) + self.send_header('Content-Type', 'text/html') + self.send_header('Content-Length', len('gotcha!')) + self.end_headers() + self.wfile.write('gotcha!') + self.wfile.close() + + self.logResponse(500) + + def log_request(code, size): + pass + +if __name__ == '__main__': + + logging.info('[ConciergeServer] Concierge Broker Test Server starting') + + parser = optparse.OptionParser() + parser.add_option('-p', '--port', dest = 'port', help = 'port to listen on', metavar = 'PORT') + parser.add_option('-f', '--fail', dest = 'fail', action = 'store_true', help = 'always fail POST requests') + + (options, args) = parser.parse_args() + + httpServer = BaseHTTPServer.HTTPServer(('', 8080), ConciergeHandler) + try: + httpServer.serve_forever() + except KeyboardInterrupt: + logging.info('[ConciergeServer] terminating') + + httpServer.server_close() diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs new file mode 100644 index 0000000..c827214 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs @@ -0,0 +1,292 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Caps=OpenSim.Framework.Communications.Capabilities.Caps; + +namespace OpenSim.Region.OptionalModules.Avatar.Voice.AsterixVoice +{ + public class AsteriskVoiceModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; + private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; + + private string m_asterisk; + private string m_asterisk_password; + private string m_asterisk_salt; + private int m_asterisk_timeout; + private string m_confDomain; + private IConfig m_config; + private Scene m_scene; + private string m_sipDomain; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_config = config.Configs["AsteriskVoice"]; + + if (null == m_config) + { + m_log.Info("[ASTERISKVOICE] no config found, plugin disabled"); + return; + } + + if (!m_config.GetBoolean("enabled", false)) + { + m_log.Info("[ASTERISKVOICE] plugin disabled by configuration"); + return; + } + m_log.Info("[ASTERISKVOICE] plugin enabled"); + + try + { + m_sipDomain = m_config.GetString("sip_domain", String.Empty); + m_log.InfoFormat("[ASTERISKVOICE] using SIP domain {0}", m_sipDomain); + + m_confDomain = m_config.GetString("conf_domain", String.Empty); + m_log.InfoFormat("[ASTERISKVOICE] using conf domain {0}", m_confDomain); + + m_asterisk = m_config.GetString("asterisk_frontend", String.Empty); + m_asterisk_password = m_config.GetString("asterisk_password", String.Empty); + m_asterisk_timeout = m_config.GetInt("asterisk_timeout", 3000); + m_asterisk_salt = m_config.GetString("asterisk_salt", "Wuffwuff"); + if (String.IsNullOrEmpty(m_asterisk)) throw new Exception("missing asterisk_frontend config parameter"); + if (String.IsNullOrEmpty(m_asterisk_password)) throw new Exception("missing asterisk_password config parameter"); + m_log.InfoFormat("[ASTERISKVOICE] using asterisk front end {0}", m_asterisk); + + scene.EventManager.OnRegisterCaps += OnRegisterCaps; + } + catch (Exception e) + { + m_log.ErrorFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.Message); + m_log.DebugFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.ToString()); + return; + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "AsteriskVoiceModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + public void OnRegisterCaps(UUID agentID, Caps caps) + { + m_log.DebugFormat("[ASTERISKVOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); + string capsBase = "/CAPS/" + caps.CapsObjectPath; + caps.RegisterHandler("ParcelVoiceInfoRequest", + new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, + delegate(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return ParcelVoiceInfoRequest(request, path, param, + agentID, caps); + })); + caps.RegisterHandler("ProvisionVoiceAccountRequest", + new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, + delegate(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return ProvisionVoiceAccountRequest(request, path, param, + agentID, caps); + })); + } + + /// + /// Callback for a client request for ParcelVoiceInfo + /// + /// + /// + /// + /// + /// + /// + public string ParcelVoiceInfoRequest(string request, string path, string param, + UUID agentID, Caps caps) + { + // we need to do: + // - send channel_uri: as "sip:regionID@m_sipDomain" + try + { + m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", + request, path, param); + + + // setup response to client + Hashtable creds = new Hashtable(); + creds["channel_uri"] = String.Format("sip:{0}@{1}", + m_scene.RegionInfo.RegionID, m_sipDomain); + + string regionName = m_scene.RegionInfo.RegionName; + ScenePresence avatar = m_scene.GetScenePresence(agentID); + if (null == m_scene.LandChannel) throw new Exception("land data not yet available"); + LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + + LLSDParcelVoiceInfoResponse parcelVoiceInfo = + new LLSDParcelVoiceInfoResponse(regionName, land.LocalID, creds); + + string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); + + + // update region on asterisk-opensim frontend + Hashtable requestData = new Hashtable(); + requestData["admin_password"] = m_asterisk_password; + requestData["region"] = m_scene.RegionInfo.RegionID.ToString(); + if (!String.IsNullOrEmpty(m_confDomain)) + { + requestData["region"] += String.Format("@{0}", m_confDomain); + } + + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest updateAccountRequest = new XmlRpcRequest("region_update", SendParams); + XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout); + Hashtable responseData = (Hashtable) updateAccountResponse.Value; + + if (!responseData.ContainsKey("success")) throw new Exception("region_update call failed"); + + bool success = Convert.ToBoolean((string) responseData["success"]); + if (!success) throw new Exception("region_update failed"); + + + m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: {0}", r); + return r; + } + catch (Exception e) + { + m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0}, retry later", e.Message); + m_log.DebugFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0} failed", e.ToString()); + + return "undef"; + } + } + + /// + /// Callback for a client request for Voice Account Details + /// + /// + /// + /// + /// + /// + /// + public string ProvisionVoiceAccountRequest(string request, string path, string param, + UUID agentID, Caps caps) + { + // we need to + // - get user data from UserProfileCacheService + // - generate nonce for user voice account password + // - issue XmlRpc request to asterisk opensim front end: + // + user: base 64 encoded user name (otherwise SL + // client is unhappy) + // + password: nonce + // - the XmlRpc call to asteris-opensim was successful: + // send account details back to client + try + { + m_log.DebugFormat("[ASTERISKVOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", + request, path, param); + + // get user data & prepare voice account response + string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes()); + voiceUser = voiceUser.Replace('+', '-').Replace('/', '_'); + + CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); + if (null == userInfo) throw new Exception("cannot get user details"); + + // we generate a nonce everytime + string voicePassword = "$1$" + Util.Md5Hash(DateTime.UtcNow.ToLongTimeString() + m_asterisk_salt); + LLSDVoiceAccountResponse voiceAccountResponse = + new LLSDVoiceAccountResponse(voiceUser, voicePassword); + string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); + m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r); + + + // update user account on asterisk frontend + Hashtable requestData = new Hashtable(); + requestData["admin_password"] = m_asterisk_password; + requestData["username"] = voiceUser; + if (!String.IsNullOrEmpty(m_sipDomain)) + { + requestData["username"] += String.Format("@{0}", m_sipDomain); + } + requestData["password"] = voicePassword; + + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest updateAccountRequest = new XmlRpcRequest("account_update", SendParams); + XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout); + Hashtable responseData = (Hashtable) updateAccountResponse.Value; + + if (!responseData.ContainsKey("success")) throw new Exception("account_update call failed"); + + bool success = Convert.ToBoolean((string) responseData["success"]); + if (!success) throw new Exception("account_update failed"); + + return r; + } + catch (Exception e) + { + m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0}, retry later", e.Message); + m_log.DebugFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0} failed", e.ToString()); + + return "undef"; + } + } + } +} diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs new file mode 100644 index 0000000..3e8a433 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs @@ -0,0 +1,202 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Caps=OpenSim.Framework.Communications.Capabilities.Caps; + +namespace OpenSim.Region.OptionalModules.Avatar.Voice.SIPVoice +{ + public class SIPVoiceModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; + private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; + private IConfig m_config; + private Scene m_scene; + private string m_sipDomain; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_config = config.Configs["Voice"]; + + if (null == m_config || !m_config.GetBoolean("enabled", false)) + { + m_log.Info("[VOICE] plugin disabled"); + return; + } + m_log.Info("[VOICE] plugin enabled"); + + m_sipDomain = m_config.GetString("sip_domain", String.Empty); + if (String.IsNullOrEmpty(m_sipDomain)) + { + m_log.Error("[VOICE] plugin mis-configured: missing sip_domain configuration"); + m_log.Info("[VOICE] plugin disabled"); + return; + } + m_log.InfoFormat("[VOICE] using SIP domain {0}", m_sipDomain); + + scene.EventManager.OnRegisterCaps += OnRegisterCaps; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "VoiceModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + public void OnRegisterCaps(UUID agentID, Caps caps) + { + m_log.DebugFormat("[VOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); + string capsBase = "/CAPS/" + caps.CapsObjectPath; + caps.RegisterHandler("ParcelVoiceInfoRequest", + new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, + delegate(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return ParcelVoiceInfoRequest(request, path, param, + agentID, caps); + })); + caps.RegisterHandler("ProvisionVoiceAccountRequest", + new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, + delegate(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return ProvisionVoiceAccountRequest(request, path, param, + agentID, caps); + })); + } + + /// + /// Callback for a client request for ParcelVoiceInfo + /// + /// + /// + /// + /// + /// + /// + public string ParcelVoiceInfoRequest(string request, string path, string param, + UUID agentID, Caps caps) + { + try + { + m_log.DebugFormat("[VOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", request, path, param); + + // FIXME: get the creds from region file or from config + Hashtable creds = new Hashtable(); + + creds["channel_uri"] = String.Format("sip:{0}@{1}", agentID, m_sipDomain); + + string regionName = m_scene.RegionInfo.RegionName; + ScenePresence avatar = m_scene.GetScenePresence(agentID); + if (null == m_scene.LandChannel) throw new Exception("land data not yet available"); + LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + + LLSDParcelVoiceInfoResponse parcelVoiceInfo = + new LLSDParcelVoiceInfoResponse(regionName, land.LocalID, creds); + + string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); + m_log.DebugFormat("[VOICE][PARCELVOICE]: {0}", r); + + return r; + } + catch (Exception e) + { + m_log.ErrorFormat("[CAPS]: {0}, try again later", e.ToString()); + } + + return null; + } + + /// + /// Callback for a client request for Voice Account Details + /// + /// + /// + /// + /// + /// + /// + public string ProvisionVoiceAccountRequest(string request, string path, string param, + UUID agentID, Caps caps) + { + try + { + m_log.DebugFormat("[VOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", + request, path, param); + + string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes()); + voiceUser = voiceUser.Replace('+', '-').Replace('/', '_'); + + CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); + if (null == userInfo) throw new Exception("cannot get user details"); + + LLSDVoiceAccountResponse voiceAccountResponse = + new LLSDVoiceAccountResponse(voiceUser, "$1$" + userInfo.UserProfile.PasswordHash); + string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); + m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r); + return r; + } + catch (Exception e) + { + m_log.ErrorFormat("[CAPS][PROVISIONVOICE]: {0}, retry later", e.Message); + } + + return null; + } + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs new file mode 100644 index 0000000..d4acc34 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs @@ -0,0 +1,161 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// AuraMetaEntity.cs created with MonoDevelop +// User: bongiojp at 3:03 PM 8/6/2008 +// +// To change standard headers go to Edit->Preferences->Coding->Standard Headers +// + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Drawing; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class AuraMetaEntity : PointMetaEntity + { + #region Constructors + + //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. + public AuraMetaEntity(Scene scene, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) + : base(scene, groupPos, transparency) + { + SetAura(color, scale); + } + + public AuraMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) + : base(scene, uuid, groupPos, transparency) + { + SetAura(color, scale); + } + + #endregion Constructors + + #region Private Methods + + private float Average(Vector3 values) + { + return (values.X + values.Y + values.Z)/3f; + } + + #endregion Private Methods + + #region Public Methods + + public void SetAura(Vector3 color, Vector3 scale) + { + SetAura(color, Average(scale) * 2.0f); + } + + public void SetAura(Vector3 color, float radius) + { + SceneObjectPart From = m_Entity.RootPart; + + //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); + float burstRadius = 0.1f; + Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; + float age = 1.5f; + float burstRate = 0.4f; + if (radius >= 8.0f) + { + //float sizeOfObject = radius / 2.0f; + burstRadius = (radius - 8.0f)/3f; + burstRate = 1.5f; + radius = 7.99f; + patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; + age = 4.0f; + } + SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); + } + + public void SetAura(SceneObjectPart From, Vector3 color, float radius, float burstRadius, float age, float burstRate, Primitive.ParticleSystem.SourcePattern patternFlags) + { + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | + // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS + //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | + // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; + prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR + prules.PartStartColor.G = color.Y; + prules.PartStartColor.B = color.Z; + prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency + prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR + prules.PartEndColor.G = color.Y; + prules.PartEndColor.B = color.Z; + prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency + /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE + prules.PartStartScaleY = 0.5f; + prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE + prules.PartEndScaleY = 0.5f; + */ + prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE + prules.PartStartScaleY = radius; + prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE + prules.PartEndScaleY = radius; + prules.PartMaxAge = age; //PSYS_PART_MAX_AGE + prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL + prules.PartAcceleration.Y = 0.0f; + prules.PartAcceleration.Z = 0.0f; + prules.Pattern = patternFlags; //PSYS_SRC_PATTERN + //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank + prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE + prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT + //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS + prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS + prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN + prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX + prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE + //prules.Target = To; //PSYS_SRC_TARGET_KEY + prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA + prules.AngularVelocity.Y = 0.0f; + prules.AngularVelocity.Z = 0.0f; + prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN + prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END + + prules.CRC = 1; //activates the particle system?? + From.AddNewParticleSystem(prules); + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs new file mode 100644 index 0000000..c0a0603 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs @@ -0,0 +1,139 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// BeamMetaEntity.cs created with MonoDevelop +// User: bongiojp at 3:03 PM 8/6/2008 +// +// To change standard headers go to Edit->Preferences->Coding->Standard Headers +// + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Drawing; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class BeamMetaEntity : PointMetaEntity + { + #region Constructors + + public BeamMetaEntity(Scene scene, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) + : base(scene, groupPos, transparency) + { + SetBeamToUUID(To, color); + } + + public BeamMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) + : base(scene, uuid, groupPos, transparency) + { + SetBeamToUUID(To, color); + } + + #endregion Constructors + + #region Public Methods + + public void SetBeamToUUID(SceneObjectPart To, Vector3 color) + { + SceneObjectPart From = m_Entity.RootPart; + //Scale size of particles to distance objects are apart (for better visibility) + Vector3 FromPos = From.GetWorldPosition(); + Vector3 ToPos = From.GetWorldPosition(); + // UUID toUUID = To.UUID; + float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + + Math.Pow(FromPos.X-ToPos.Y, 2) + + Math.Pow(FromPos.X-ToPos.Z, 2) + ) + ); + //float rate = (float) (distance/4f); + float rate = 0.5f; + float scale = (float) (distance/128f); + float speed = (float) (2.0f - distance/128f); + + SetBeamToUUID(From, To, color, rate, scale, speed); + } + + public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, Vector3 color, float rate, float scale, float speed) + { + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | + // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS + prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | + Primitive.ParticleSystem.ParticleDataFlags.TargetPos; + prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR + prules.PartStartColor.G = color.Y; + prules.PartStartColor.B = color.Z; + prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency + prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR + prules.PartEndColor.G = color.Y; + prules.PartEndColor.B = color.Z; + prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency + prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE + prules.PartStartScaleY = scale; + prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE + prules.PartEndScaleY = scale; + prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE + prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL + prules.PartAcceleration.Y = 0.0f; + prules.PartAcceleration.Z = 0.0f; + //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN + //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank + prules.BurstRate = rate; //PSYS_SRC_BURST_RATE + prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT + prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS + prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN + prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX + prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE + prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY + prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA + prules.AngularVelocity.Y = 0.0f; + prules.AngularVelocity.Z = 0.0f; + prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN + prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END + + prules.CRC = 1; //activates the particle system?? + From.AddNewParticleSystem(prules); + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs new file mode 100644 index 0000000..80989a7 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs @@ -0,0 +1,757 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// CMController.cs +// User: bongiojp +// + +#endregion Header + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; + +using OpenMetaverse; + +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + /// + /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread, + /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system. + /// + public class CMController + { + #region Static Fields + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. + /// + private static OpenSim.Framework.BlockingQueue m_WorkQueue = new OpenSim.Framework.BlockingQueue(); + + #endregion Static Fields + + #region Fields + + //bool init = false; + int m_channel = -1; + + /// + /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. + /// + IEstateModule m_estateModule = null; + + //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) + CMModel m_model = null; + + /// + /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. + /// + Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); + State m_state = State.NONE; + Thread m_thread = null; + CMView m_view = null; + + #endregion Fields + + #region Constructors + + /// + /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. + /// + /// + /// + /// + /// + /// + /// + /// + /// The first scene to keep track of. + /// + /// + /// The simchat channel number to listen to for instructions + /// + public CMController(CMModel model, CMView view, Scene scene, int channel) + { + m_model = model; m_view = view; m_channel = channel; + RegisterNewRegion(scene); + Initialize(model, view, scene, channel); + } + + #endregion Constructors + + #region Private Methods + + //------------------------------------------------ EVENTS ----------------------------------------------------// +// private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) +// { +// } + + /// + /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned. + /// + private SceneObjectGroup GetGroupByPrim(uint localID) + { + foreach (Object currScene in m_sceneList.Values) + { + foreach (EntityBase ent in ((Scene)currScene).GetEntities()) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup)ent).HasChildPrim(localID)) + return (SceneObjectGroup)ent; + } + } + } + return null; + } + + private void Initialize(CMModel model, CMView view, Scene scene, int channel) + { + lock (this) + { + m_estateModule = scene.RequestModuleInterface(); + m_thread = new Thread(MainLoop); + m_thread.Name = "Content Management"; + m_thread.IsBackground = true; + m_thread.Start(); + ThreadTracker.Add(m_thread); + m_state = State.NONE; + } + } + + /// + /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions. + /// + private void MainLoop() + { + try + { + CMModel model = m_model; CMView view = m_view; int channel = m_channel; + Work currentJob = new Work(); + while (true) + { + currentJob = m_WorkQueue.Dequeue(); + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); + switch (currentJob.Type) + { + case WorkType.NONE: + break; + case WorkType.OBJECTATTRIBUTECHANGE: + ObjectAttributeChanged(model, view, currentJob.LocalId); + break; + case WorkType.PRIMITIVEADDED: + PrimitiveAdded(model, view, currentJob); + break; + case WorkType.OBJECTDUPLICATED: + ObjectDuplicated(model, view, currentJob.LocalId); + break; + case WorkType.OBJECTKILLED: + ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); + break; + case WorkType.UNDODID: + UndoDid(model, view, currentJob.UUID); + break; + case WorkType.NEWCLIENT: + NewClient(view, (IClientAPI) currentJob.Data1); + break; + case WorkType.SIMCHAT: + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); + SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); + break; + default: + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); + break; + } + } + } + catch (Exception e) + { + // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened + m_log.ErrorFormat( + "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", + e); + } + } + + /// + /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. + /// + private void NewClient(CMView view, IClientAPI client) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + view.SendMetaEntitiesToNewClient(client); + } + + /// + /// Only called by the MainLoop. + /// + private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) + { + SceneObjectGroup group = null; + if ((m_state & State.SHOWING_CHANGES) > 0) + { + group = GetGroupByPrim(LocalId); + if (group != null) + { + view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura) + m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) + } + } + } + + /// + /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. + /// + private void ObjectDuplicated(CMModel model, CMView view, uint localId) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); + } + + /// + /// Only called by the MainLoop. + /// + private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + view.RemoveOrUpdateDeletedEntity(group); + model.RemoveOrUpdateDeletedEntity(group); + } + } + + /// + /// Only called by the MainLoop. + /// + private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + foreach (Object scene in m_sceneList.Values) + m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); + } + } + + /// + /// Only called by the MainLoop. + /// + private void UndoDid(CMModel model, CMView view, UUID uuid) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); + if (ent != null) + view.DisplayEntity(ent); + } + } + + #endregion Private Methods + + #region Protected Methods + + protected void GroupBeingDeleted(SceneObjectGroup group) + { + m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTKILLED; + moreWork.Data1 = group.Copy(); + m_WorkQueue.Enqueue(moreWork); + } + + protected void ObjectDuplicated(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTDUPLICATED; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] dup queue"); + } + + protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, + UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, + bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTDUPLICATED; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] dup queue"); + } + + protected void OnNewClient(IClientAPI client) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.NEWCLIENT; + moreWork.Data1 = client; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] new client"); + } + + protected void OnUnDid(IClientAPI remoteClient, UUID primId) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.UNDODID; + moreWork.UUID = primId; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] undid"); + } + + /// + /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. + /// + protected static System.Collections.Generic.List ScenesInOrderOfProximity(Hashtable sceneList, Scene scene) + { + int somethingAddedToList = 1; + System.Collections.Generic.List newList = new List(); + newList.Add(scene); + + if (!sceneList.ContainsValue(scene)) + { + foreach (Object sceneObj in sceneList) + newList.Add((Scene) sceneObj); + return newList; + } + + while (somethingAddedToList > 0) + { + somethingAddedToList = 0; + for (int i = 0; i < newList.Count; i++) + { + foreach (Object sceneObj in sceneList.Values) + { + if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (!newList.Contains((Scene)sceneObj))) + { + newList.Add((Scene)sceneObj); + somethingAddedToList++; + } + } + } + } + + foreach (Object sceneObj in sceneList.Values) + if (!newList.Contains((Scene)sceneObj)) + newList.Add((Scene)sceneObj); + + return newList; + } + + //This is stupid, the same information is contained in the first and second argument + protected void SimChatSent(Object x, OSChatMessage e) + { + m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); + m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); + Work moreWork = new Work(); + moreWork.Type = WorkType.SIMCHAT; + moreWork.Data1 = e; + m_WorkQueue.Enqueue(moreWork); + } + + /// + /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. + /// + protected void StartManaging(IClientAPI client) + { + m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); + // client.OnChatFromClient += SimChatSent; + //init = true; + + OnNewClient(client); + + m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); + client.OnUpdatePrimScale += UpdateSingleScale; + client.OnUpdatePrimGroupScale += UpdateMultipleScale; + client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; + client.OnUpdatePrimSinglePosition += UpdateSinglePosition; + client.OnUpdatePrimGroupRotation += UpdateMultipleRotation; + client.OnUpdatePrimSingleRotation += UpdateSingleRotation; + client.OnAddPrim += UpdateNewParts; + client.OnObjectDuplicate += ObjectDuplicated; + client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay; + client.OnUndo += OnUnDid; + //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; + } + + /// + /// + /// + protected void StopManaging(UUID clientUUID) + { + foreach (Object sceneobj in m_sceneList.Values) + { + ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); + if (presence != null) + { + IClientAPI client = presence.ControllingClient; + m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); + // client.OnChatFromViewer -= SimChatSent; + + m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); + client.OnUpdatePrimScale -= UpdateSingleScale; + client.OnUpdatePrimGroupScale -= UpdateMultipleScale; + client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; + client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; + client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; + client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; + client.OnAddPrim -= UpdateNewParts; + client.OnObjectDuplicate -= ObjectDuplicated; + client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; + client.OnUndo -= OnUnDid; + //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; + return; + } + } + } + + protected void UpdateMultiplePosition(uint localID, Vector3 pos, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] pos"); + } + + protected void UpdateMultipleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] rot"); + } + + protected void UpdateMultipleScale(uint localID, Vector3 scale, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT]scale"); + } + + protected void UpdateNewParts(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, + byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, + byte RayEndIsIntersection) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.PRIMITIVEADDED; + moreWork.UUID = ownerID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] new parts"); + } + + protected void UpdateSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] move"); + } + + /// + /// + /// + protected void UpdateSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] rot"); + } + + protected void UpdateSingleScale(uint localID, Vector3 scale, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] scale"); + } + + /// + /// Only called from within the SimChat method. + /// + protected void commit(string message, Scene scene, CMModel model, CMView view) + { + System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); + + string[] args = message.Split(new char[] {' '}); + + char[] logMessage = {' '}; + if (args.Length > 1) + { + logMessage = new char[message.Length - (args[0].Length)]; + message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); + } + + m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); + foreach (Scene currScene in proximitySceneList) + { + model.CommitRegion(currScene, new String(logMessage)); + view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); + } + + view.SendSimChatMessage(scene, "Successfully saved all regions."); + m_state |= State.DIRTY; + + if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES + { + view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); + //Hide objects from users and Forget about them + view.HideAllMetaEntities(); + view.HideAllAuras(); + model.DeleteAllMetaObjects(); + + //Recreate them from backend files + foreach (Scene currScene in proximitySceneList) + { + model.UpdateCMEntities(currScene); + view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); + } + + //Display new objects to users1 + view.DisplayRecentChanges(); + view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); + m_state &= ~(State.DIRTY); + m_state |= State.SHOWING_CHANGES; + } + } + + /// + /// Only called from within the SimChat method. + /// + protected void diffmode(Scene scene, CMModel model, CMView view) + { + System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); + + if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF + { + view.SendSimChatMessage(scene, "Hiding all meta objects."); + view.HideAllMetaEntities(); + view.HideAllAuras(); + view.SendSimChatMessage(scene, "Diff-mode = OFF"); + + m_state &= ~State.SHOWING_CHANGES; + return; + } + else // TURN ON + { + if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) + { + view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); + //Hide objects from users and Forget about them + view.HideAllMetaEntities(); + view.HideAllAuras(); + model.DeleteAllMetaObjects(); + //Recreate them from backend files + foreach (Object currScene in m_sceneList.Values) + model.UpdateCMEntities((Scene) currScene); + } + else if ((m_state & State.DIRTY) != 0) { + view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); + foreach (Scene currScene in proximitySceneList) + model.UpdateCMEntities(currScene); + } + + view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); + foreach (Scene currScene in proximitySceneList) + model.CheckForNewEntitiesMissingAuras(currScene); + view.DisplayRecentChanges(); + + view.SendSimChatMessage(scene, "Diff-mode = ON"); + m_state |= State.SHOWING_CHANGES; + m_state &= ~State.DIRTY; + } + } + + /// + /// Only called from within the SimChat method. Hides all auras and meta entities, + /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, + /// then lets the view update the clients of the new objects. + /// + protected void rollback(Scene scene, CMModel model, CMView view) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + view.HideAllAuras(); + view.HideAllMetaEntities(); + } + + System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); + foreach (Scene currScene in proximitySceneList) + model.RollbackRegion(currScene); + + if ((m_state & State.DIRTY) != 0) + { + model.DeleteAllMetaObjects(); + foreach (Scene currScene in proximitySceneList) + model.UpdateCMEntities(currScene); + } + + if ((m_state & State.SHOWING_CHANGES) > 0) + view.DisplayRecentChanges(); + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. + /// + /// + /// A + /// + public void RegisterNewRegion(Scene scene) + { + m_sceneList.Add(scene.RegionInfo.RegionID, scene); + + m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); + m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); + + scene.EventManager.OnNewClient += StartManaging; + scene.EventManager.OnChatFromClient += SimChatSent; + scene.EventManager.OnRemovePresence += StopManaging; + // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; + scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; + } + + /// + /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. + /// + public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) + { + if (e.Channel != channel) + return; + if (e.Sender == null) + return; + + m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); + + IClientAPI client = e.Sender; + Scene scene = (Scene) e.Scene; + string message = e.Message; + string[] args = e.Message.Split(new char[] {' '}); + + ScenePresence avatar = scene.GetScenePresence(client.AgentId); + + if (!(m_estateModule.IsManager(avatar.UUID))) + { + m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); + view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); + return; + } + + switch (args[0]) + { + case "ci": + case "commit": + commit(message, scene, model, view); + break; + case "dm": + case "diff-mode": + diffmode(scene, model, view); + break; + case "rb": + case "rollback": + rollback(scene, model, view); + break; + case "help": + m_view.DisplayHelpMenu(scene); + break; + default: + view.SendSimChatMessage(scene, "Command not found: " + args[0]); + break; + } + } + + #endregion Public Methods + + #region Other + + /// + /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk. + /// + [Flags] + private enum State + { + NONE = 0, + DIRTY = 1, // The meta entities may not correctly represent the last revision. + SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. + } + + /// + /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. + /// + private struct Work + { + #region Fields + + public Object Data1; //Just space for holding data. + public Object Data2; //Just more space for holding data. + public uint LocalId; //Convenient + public WorkType Type; + public UUID UUID; //Convenient + + #endregion Fields + } + + /// + /// Identifies what the data in struct Work should be used for. + /// + private enum WorkType + { + NONE, + OBJECTATTRIBUTECHANGE, + PRIMITIVEADDED, + OBJECTDUPLICATED, + OBJECTKILLED, + UNDODID, + NEWCLIENT, + SIMCHAT + } + + #endregion Other + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs new file mode 100644 index 0000000..d5cf596 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs @@ -0,0 +1,193 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// CMEntityCollection.cs created with MonoDevelop +// User: bongiojp at 10:09 AM 7/7/2008 +// +// Creates, Deletes, Stores ContentManagementEntities +// + +#endregion Header + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class CMEntityCollection + { + #region Fields + + // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or + // old versions of deleted SceneObjectGroups will be stored in this hash table. + // The UUID keys are from the SceneObjectGroup RootPart UUIDs + protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //UUID to ContentManagementEntity + + // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable + // The UUID keys are from the SceneObjectPart that they are supposed to be on. + protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //UUID to AuraMetaEntity + + #endregion Fields + + #region Constructors + + public CMEntityCollection() + { + } + + #endregion Constructors + + #region Public Properties + + public Hashtable Auras + { + get {return m_NewlyCreatedEntityAura; } + } + + public Hashtable Entities + { + get { return m_CMEntityHash; } + } + + #endregion Public Properties + + #region Public Methods + + public bool AddAura(ContentManagementEntity aura) + { + if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) + return false; + m_NewlyCreatedEntityAura.Add(aura.UUID, aura); + return true; + } + + public bool AddEntity(ContentManagementEntity ent) + { + if (m_CMEntityHash.ContainsKey(ent.UUID)) + return false; + m_CMEntityHash.Add(ent.UUID, ent); + return true; + } + + // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash + public System.Collections.ArrayList CheckForMissingEntities(System.Collections.Generic.List currList) + { + System.Collections.ArrayList missingList = new System.Collections.ArrayList(); + SceneObjectGroup temp = null; + foreach (EntityBase currObj in currList) + { + if (!(currObj is SceneObjectGroup)) + continue; + temp = (SceneObjectGroup) currObj; + + if (m_CMEntityHash.ContainsKey(temp.UUID)) + { + foreach (SceneObjectPart part in temp.Children.Values) + if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) + missingList.Add(part); + } + else //Entire group is missing from revision. (and is a new part in region) + { + foreach (SceneObjectPart part in temp.Children.Values) + missingList.Add(part); + } + } + return missingList; + } + + public void ClearAll() + { + m_CMEntityHash.Clear(); + m_NewlyCreatedEntityAura.Clear(); + } + + // Old uuid and new sceneobjectgroup + public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) + { + AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, + part.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new Vector3(0,254,0), + part.Scale + ); + m_NewlyCreatedEntityAura.Add(part.UUID, ent); + return ent; + } + + // Old uuid and new sceneobjectgroup + public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) + { + ContentManagementEntity ent = new ContentManagementEntity(group, false); + m_CMEntityHash.Add(group.UUID, ent); + return ent; + } + + public ContentManagementEntity CreateNewEntity(String xml, Scene scene) + { + ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); + if (ent == null) + return null; + m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); + return ent; + } + + public bool RemoveEntity(UUID uuid) + { + if (!m_CMEntityHash.ContainsKey(uuid)) + return false; + m_CMEntityHash.Remove(uuid); + return true; + } + + public bool RemoveNewlyCreatedEntityAura(UUID uuid) + { + if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) + return false; + m_NewlyCreatedEntityAura.Remove(uuid); + return true; + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs new file mode 100644 index 0000000..761dca9 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs @@ -0,0 +1,362 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// CMModel.cs +// User: bongiojp +// +// + +#endregion Header + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; + +using OpenMetaverse; + +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class CMModel + { + #region Static Fields + + static float TimeToUpdate = 0; + static float TimeToConvertXml = 0; + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + /// + /// The class that contains all auras and metaentities used in the CMS. + /// + CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); + IContentDatabase m_database = null; + + #endregion Fields + + #region Constructors + + public CMModel() + { + } + + #endregion Constructors + + #region Public Properties + + public CMEntityCollection MetaEntityCollection + { + get { return m_MetaEntityCollection; } + } + + #endregion Public Properties + + #region Public Methods + + /// + /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity + /// it is a new part that must have a green aura (for diff mode). + /// Returns list of ContentManagementEntities + /// + public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) + { + ArrayList missingList = null; + ArrayList newList = new ArrayList(); + + m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); + + //Check if the current scene has groups not included in the current list of MetaEntities + //If so, then the current scene's parts that are new should be marked green. + missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); + + foreach (Object missingPart in missingList) + { + if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) + continue; + newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); + } + m_log.Info("Number of missing objects found: " + newList.Count); + return newList; + } + + /// + /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. + /// + public void CommitRegion(Scene scene, String logMessage) + { + m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); + m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); + m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName ); + } + + public void DeleteAllMetaObjects() + { + m_MetaEntityCollection.ClearAll(); + } + + public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid) + { + ContentManagementEntity ent = GetMetaGroupByPrim(uuid); + return ent; + } + + //-------------------------------- HELPERS --------------------------------------------------------------------// + public ContentManagementEntity GetMetaGroupByPrim(UUID uuid) + { + foreach (Object ent in m_MetaEntityCollection.Entities.Values) + { + if (((ContentManagementEntity)ent).HasChildPrim(uuid)) + return (ContentManagementEntity)ent; + } + return null; + } + + public void Initialise(string database) + { + if (database == "FileSystemDatabase") + m_database = new FileSystemDatabase(); + else if (database == "GitDatabase") + m_database = new GitDatabase(); + } + + public void InitialiseDatabase(Scene scene, string dir) + { + m_database.Initialise(scene, dir); + } + + /// + /// Should be called just once to finish initializing the database. + /// + public void PostInitialise() + { + m_database.PostInitialise(); + } + + /// + /// Removes the green aura when an a new scene object group is deleted. + /// + public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) + { + // Deal with new parts not revisioned that have been deleted. + foreach (SceneObjectPart part in group.Children.Values) + if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) + m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); + } + + /// + /// Retrieves the latest revision of a region in xml form, + /// converts it to scene object groups and scene presences, + /// swaps the current scene's entity list with the revision's list. + /// Note: Since deleted objects while + /// + public void RollbackRegion(Scene scene) + { + System.Collections.ArrayList xmllist = null; + SceneObjectGroup temp = null; + System.Collections.Hashtable deleteListUUIDs = new Hashtable(); +// Dictionary SearchList = new Dictionary(); + Dictionary ReplacementList = new Dictionary(); + int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); +// EntityBase[] searchArray; + + xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); + if (xmllist == null) + { + m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); + return; + } + + m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); + m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); + m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); + + m_log.ErrorFormat("[CMMODEL]: 1"); + + foreach (string xml in xmllist) + { + try{ + temp = new SceneObjectGroup(xml); + temp.SetScene(scene); + foreach (SceneObjectPart part in temp.Children.Values) + part.RegionHandle = scene.RegionInfo.RegionHandle; + ReplacementList.Add(temp.UUID, (EntityBase)temp); + } + catch(Exception e) + { + m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e); + } + } + + //If in scene but not in revision and not a client, remove them + while (true) + { + try + { + foreach (EntityBase entity in scene.GetEntities()) + { + if (entity == null) + continue; + + if (entity is ScenePresence) + { + ReplacementList.Add(entity.UUID, entity); + continue; + } + else //if (!ReplacementList.ContainsKey(entity.UUID)) + deleteListUUIDs.Add(entity.UUID, 0); + } + } + catch(Exception e) + { + m_log.ErrorFormat("[CMMODEL]: " + e); + deleteListUUIDs.Clear(); + ReplacementList.Clear(); + continue; + } + break; + } + + foreach (UUID uuid in deleteListUUIDs.Keys) + { + try + { + // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. + ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); + scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); + scene.SendKillObject(scene.Entities[uuid].LocalId); + scene.m_sceneGraph.DeleteSceneObject(uuid, false); + ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup(false); + } + catch(Exception e) + { + m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); + } + } + + lock (scene) + { + scene.Entities.Clear(); + + foreach (KeyValuePair kvp in ReplacementList) + { + scene.Entities.Add(kvp.Value); + } + } + + foreach (EntityBase ent in ReplacementList.Values) + { + try + { + if (!(ent is SceneObjectGroup)) + continue; + + if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0) + ((SceneObjectGroup)ent).ApplyPhysics(true); + ((SceneObjectGroup)ent).AttachToBackup(); + ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. + ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); + } + catch(Exception e) + { + m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e); + } + } + m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); + scene.Backup(); + } + + /// + /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences + /// and display the differences to clients. + /// + public void UpdateCMEntities(Scene scene) + { + Stopwatch x = new Stopwatch(); + x.Start(); + + System.Collections.ArrayList xmllist = null; + m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID); + xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID); + m_log.Info("[FSDB]: got list"); + if (xmllist == null) + return; + + Stopwatch y = new Stopwatch(); + y.Start(); + foreach (string xml in xmllist) + m_MetaEntityCollection.CreateNewEntity(xml, scene); + y.Stop(); + TimeToConvertXml += y.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); + m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); + + m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); + CheckForNewEntitiesMissingAuras(scene); + + x.Stop(); + TimeToUpdate += x.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); + m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); + } + + /// + /// Detects if a scene object group from the scene list has moved or changed scale. The green aura + /// that surrounds the object is then moved or scaled with the group. + /// + public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) + { + System.Collections.ArrayList auraList = new System.Collections.ArrayList(); + if (group == null) + return null; + foreach (SceneObjectPart part in group.Children.Values) + { + if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) + { + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale); + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); + auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); + } + } + return auraList; + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs new file mode 100644 index 0000000..a1a4d94 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs @@ -0,0 +1,206 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// CMView.cs created with MonoDevelop +// User: bongiojp at 11:57 AM 7/3/2008 +// +// To change standard headers go to Edit->Preferences->Coding->Standard Headers +// + +#endregion Header + +using System; +using System.Collections; +using System.Collections.Generic; + +using OpenMetaverse; + +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class CMView + { + #region Static Fields + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + CMModel m_model = null; + + #endregion Fields + + #region Constructors + + public CMView() + { + } + + #endregion Constructors + + #region Public Methods + + // Auras To + public void DisplayAuras(CMEntityCollection auraCollection) + { + foreach (Object ent in auraCollection.Auras.Values) + ((AuraMetaEntity)ent).SendFullUpdateToAll(); + } + + // Auras To Client + public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) + { + foreach (Object ent in auraCollection.Auras.Values) + ((AuraMetaEntity)ent).SendFullUpdate(client); + } + + // Auras from List To ALL + public void DisplayAuras(ArrayList list) + { + foreach (Object ent in list) + { + m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); + ((AuraMetaEntity)ent).SendFullUpdateToAll(); + } + } + + // Entities to ALL + public void DisplayEntities(CMEntityCollection entityCollection) + { + foreach (Object ent in entityCollection.Entities.Values) + ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); + } + + // Entities to Client + public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) + { + foreach (Object ent in entityCollection.Entities.Values) + ((ContentManagementEntity)ent).SendFullDiffUpdate(client); + } + + // Entities from List to ALL + public void DisplayEntities(ArrayList list) + { + foreach (Object ent in list) + ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); + } + + // Entity to ALL + public void DisplayEntity(ContentManagementEntity ent) + { + ent.SendFullDiffUpdateToAll(); + } + + public void DisplayHelpMenu(Scene scene) + { + string menu = "Menu:\n"; + menu += "commit (ci) - saves current state of the region to a database on the server\n"; + menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n"; + SendSimChatMessage(scene, menu); + } + + public void DisplayMetaEntity(UUID uuid) + { + ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); + if (group != null) + group.SendFullDiffUpdateToAll(); + } + + /// + /// update all clients of red/green/blue auras and meta entities that the model knows about. + /// + public void DisplayRecentChanges() + { + m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); + DisplayEntities(m_model.MetaEntityCollection); + DisplayAuras(m_model.MetaEntityCollection); + } + + public void Hide(ContentManagementEntity ent) + { + ent.HideFromAll(); + } + + public void HideAllAuras() + { + foreach (Object obj in m_model.MetaEntityCollection.Auras.Values) + ((MetaEntity)obj).HideFromAll(); + } + + public void HideAllMetaEntities() + { + foreach (Object obj in m_model.MetaEntityCollection.Entities.Values) + ((ContentManagementEntity)obj).HideFromAll(); + } + + public void Initialise(CMModel model) + { + m_model = model; + } + + /// + /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. + /// If it's a new scene object, any green aura attached to it is deleted. + /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will + /// figure out that there should be a red aura and not a blue aura/beam. + /// + public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) + { + // Deal with revisioned parts that have been deleted. + if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) + ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); + + // Deal with new parts not revisioned that have been deleted. + foreach (SceneObjectPart part in group.Children.Values) + if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) + ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); + } + + public void SendMetaEntitiesToNewClient(IClientAPI client) + { + } + + public void SendSimChatMessage(Scene scene, string message) + { + scene.SimChat(Utils.StringToBytes(message), + ChatTypeEnum.Broadcast, 0, new Vector3(0,0,0), "Content Manager", UUID.Zero, false); + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs new file mode 100644 index 0000000..4d65038 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs @@ -0,0 +1,383 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// ContentManagementEntity.cs +// User: bongiojp +// +// + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Drawing; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class ContentManagementEntity : MetaEntity + { + #region Static Fields + +// static float TimeToDiff = 0; +// static float TimeToCreateEntities = 0; + + #endregion Static Fields + + #region Fields + + protected Dictionary m_AuraEntities = new Dictionary(); + protected Dictionary m_BeamEntities = new Dictionary(); + + // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. + // This can come in handy. + protected SceneObjectGroup m_UnchangedEntity = null; + + /// + /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. + /// + bool DiffersFromSceneGroup = false; + + #endregion Fields + + #region Constructors + + public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) + : base(Unchanged, false) + { + m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false); + } + + public ContentManagementEntity(string objectXML, Scene scene, bool physics) + : base(objectXML, scene, false) + { + m_UnchangedEntity = new SceneObjectGroup(objectXML); + } + + #endregion Constructors + + #region Public Properties + + public SceneObjectGroup UnchangedEntity + { + get { return m_UnchangedEntity; } + } + + #endregion Public Properties + + #region Private Methods + + /// + /// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid. + /// + private bool ContainsKey(List list, UUID uuid) + { + foreach (EntityBase part in list) + if (part.UUID == uuid) + return true; + return false; + } + + private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List list, UUID uuid) + { + foreach (EntityBase ent in list) + { + if (ent is SceneObjectGroup) + if (ent.UUID == uuid) + return (SceneObjectGroup)ent; + } + return null; + } + + #endregion Private Methods + + #region Public Methods + + /// + /// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately. + /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. + /// + public void FindDifferences() + { + System.Collections.Generic.List sceneEntityList = m_Entity.Scene.GetEntities(); + DiffersFromSceneGroup = false; + // if group is not contained in scene's list + if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) + { + foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) + { + // if scene list no longer contains this part, display translucent part and mark with red aura + if (!ContainsKey(sceneEntityList, part.UUID)) + { + // if already displaying a red aura over part, make sure its red + if (m_AuraEntities.ContainsKey(part.UUID)) + { + m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale); + } + else + { + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + part.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new Vector3(254,0,0), + part.Scale + ); + m_AuraEntities.Add(part.UUID, auraGroup); + } + SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); + SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); + } + // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id + } + + // a deleted part has no where to point a beam particle system, + // if a metapart had a particle system (maybe it represented a moved part) remove it + if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) + { + m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); + m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); + } + + DiffersFromSceneGroup = true; + } + // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately + else + { + MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); + } + } + + /// + /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. + /// + public bool HasChildPrim(UUID uuid) + { + if (m_UnchangedEntity.Children.ContainsKey(uuid)) + return true; + return false; + } + + /// + /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. + /// + public bool HasChildPrim(uint localID) + { + foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) + if (part.LocalId == localID) + return true; + return false; + } + + public override void Hide(IClientAPI client) + { + base.Hide(client); + foreach (MetaEntity group in m_AuraEntities.Values) + group.Hide(client); + foreach (MetaEntity group in m_BeamEntities.Values) + group.Hide(client); + } + + public override void HideFromAll() + { + base.HideFromAll(); + foreach (MetaEntity group in m_AuraEntities.Values) + group.HideFromAll(); + foreach (MetaEntity group in m_BeamEntities.Values) + group.HideFromAll(); + } + + /// + /// Returns true if there was a change between meta entity and the entity group, false otherwise. + /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). + /// + public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) + { + SceneObjectPart sceneEntityPart; + SceneObjectPart metaEntityPart; + Diff differences; + bool changed = false; + + // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user + // had originally saved. + // m_Entity will NOT necessarily be the same entity as the user had saved. + foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) + { + //This is the part that we use to show changes. + metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); + if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) + { + sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; + differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); + if (differences != Diff.NONE) + metaEntityPart.Text = "CHANGE: " + differences.ToString(); + if (differences != 0) + { + // Root Part that has been modified + if ((differences&Diff.POSITION) > 0) + { + // If the position of any part has changed, make sure the RootPart of the + // meta entity is pointing with a beam particle system + if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) + { + m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); + m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); + } + BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, + m_UnchangedEntity.RootPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + sceneEntityPart, + new Vector3(0,0,254) + ); + m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); + } + + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + UnchangedPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new Vector3(0,0,254), + UnchangedPart.Scale + ); + m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); + SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); + + DiffersFromSceneGroup = true; + } + else // no differences between scene part and meta part + { + if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) + { + m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); + m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); + } + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + SetPartTransparency(metaEntityPart, MetaEntity.NONE); + } + } + else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. + { + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + UnchangedPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new Vector3(254,0,0), + UnchangedPart.Scale + ); + m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); + SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); + + DiffersFromSceneGroup = true; + } + } + return changed; + } + + public void SendFullAuraUpdate(IClientAPI client) + { + if (DiffersFromSceneGroup) + { + foreach (AuraMetaEntity group in m_AuraEntities.Values) + group.SendFullUpdate(client); + } + } + + public void SendFullAuraUpdateToAll() + { + if (DiffersFromSceneGroup) + { + foreach (AuraMetaEntity group in m_AuraEntities.Values) + group.SendFullUpdateToAll(); + } + } + + public void SendFullBeamUpdate(IClientAPI client) + { + if (DiffersFromSceneGroup) + { + foreach (BeamMetaEntity group in m_BeamEntities.Values) + group.SendFullUpdate(client); + } + } + + public void SendFullBeamUpdateToAll() + { + if (DiffersFromSceneGroup) + { + foreach (BeamMetaEntity group in m_BeamEntities.Values) + group.SendFullUpdateToAll(); + } + } + + public void SendFullDiffUpdate(IClientAPI client) + { + FindDifferences(); + if (DiffersFromSceneGroup) + { + SendFullUpdate(client); + SendFullAuraUpdate(client); + SendFullBeamUpdate(client); + } + } + + public void SendFullDiffUpdateToAll() + { + FindDifferences(); + if (DiffersFromSceneGroup) + { + SendFullUpdateToAll(); + SendFullAuraUpdateToAll(); + SendFullBeamUpdateToAll(); + } + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs new file mode 100644 index 0000000..21bc8b2 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs @@ -0,0 +1,163 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// ContentManagementModule.cs +// User: bongiojp + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Threading; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class ContentManagementModule : IRegionModule + { + #region Static Fields + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + bool initialised = false; + CMController m_control = null; + bool m_enabled = false; + CMModel m_model = null; + bool m_posted = false; + CMView m_view = null; + + #endregion Fields + + #region Public Properties + + public bool IsSharedModule + { + get { return true; } + } + + public string Name + { + get { return "ContentManagementModule"; } + } + + #endregion Public Properties + + #region Public Methods + + public void Close() + { + } + + public void Initialise(Scene scene, IConfigSource source) + { + string databaseDir = "./"; + string database = "FileSystemDatabase"; + int channel = 345; + try + { + if (source.Configs["CMS"] == null) + return; + + m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); + databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); + database = source.Configs["CMS"].GetString("database", database); + channel = source.Configs["CMS"].GetInt("channel", channel); + + if (database != "FileSystemDatabase" && database != "GitDatabase") + { + m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); + m_enabled = false; + } + } + catch (Exception e) + { + m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); + m_enabled = false; + } + + if (!m_enabled) + { + m_log.Info("[Content Management]: Content Management System is not Enabled."); + return; + } + + lock (this) + { + if (!initialised) //only init once + { + m_view = new CMView(); + m_model = new CMModel(); + m_control = new CMController(m_model, m_view, scene, channel); + m_model.Initialise(database); + m_view.Initialise(m_model); + + initialised = true; + m_model.InitialiseDatabase(scene, databaseDir); + } + else + { + m_model.InitialiseDatabase(scene, databaseDir); + m_control.RegisterNewRegion(scene); + } + } + } + + public void PostInitialise() + { + if (! m_enabled) + return; + + lock (this) + { + if (!m_posted) //only post once + { + m_model.PostInitialise(); + m_posted = true; + } + } + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs new file mode 100644 index 0000000..6a50906 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs @@ -0,0 +1,317 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// FileSystemDatabase.cs +// User: bongiojp + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using Slash = System.IO.Path; +using System.Reflection; +using System.Xml; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class FileSystemDatabase : IContentDatabase + { + #region Static Fields + + public static float TimeToDownload = 0; + public static float TimeToSave = 0; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + private string m_repodir = null; + private Dictionary m_scenes = new Dictionary(); + private Dictionary m_serialiser = new Dictionary(); + + #endregion Fields + + #region Constructors + + public FileSystemDatabase() + { + } + + #endregion Constructors + + #region Private Methods + + // called by postinitialise + private void CreateDirectory() + { + string scenedir; + if (!Directory.Exists(m_repodir)) + Directory.CreateDirectory(m_repodir); + + foreach (UUID region in m_scenes.Keys) + { + scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; + if (!Directory.Exists(scenedir)) + Directory.CreateDirectory(scenedir); + } + } + + // called by postinitialise + private void SetupSerialiser() + { + if (m_serialiser.Count == 0) + { + foreach (UUID region in m_scenes.Keys) + { + m_serialiser.Add(region, m_scenes[region].RequestModuleInterface()); + } + } + } + + #endregion Private Methods + + #region Public Methods + + public int GetMostRecentRevision(UUID regionid) + { + return NumOfRegionRev(regionid); + } + + public string GetRegionObjectHeightMap(UUID regionid) + { + String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + + Slash.DirectorySeparatorChar + "heightmap.r32"; + FileStream fs = new FileStream( filename, FileMode.Open); + StreamReader sr = new StreamReader(fs); + String result = sr.ReadToEnd(); + sr.Close(); + fs.Close(); + return result; + } + + public string GetRegionObjectHeightMap(UUID regionid, int revision) + { + String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + + Slash.DirectorySeparatorChar + "heightmap.r32"; + FileStream fs = new FileStream( filename, FileMode.Open); + StreamReader sr = new StreamReader(fs); + String result = sr.ReadToEnd(); + sr.Close(); + fs.Close(); + return result; + } + + public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) + { + System.Collections.ArrayList objectList = new System.Collections.ArrayList(); + string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + + + revision + Slash.DirectorySeparatorChar + "objects.xml"; + XmlDocument doc = new XmlDocument(); + XmlNode rootNode; + //int primCount = 0; + //SceneObjectGroup obj = null; + + if (File.Exists(filename)) + { + XmlTextReader reader = new XmlTextReader(filename); + reader.WhitespaceHandling = WhitespaceHandling.None; + doc.Load(reader); + reader.Close(); + rootNode = doc.FirstChild; + foreach (XmlNode aPrimNode in rootNode.ChildNodes) + { + objectList.Add(aPrimNode.OuterXml); + } + return objectList; + } + return null; + } + + public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) + { + int revision = NumOfRegionRev(regionid); + m_log.Info("[FSDB]: found revisions:" + revision); + System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); + string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + + + revision + Slash.DirectorySeparatorChar + "objects.xml"; + XmlDocument doc = new XmlDocument(); + XmlNode rootNode; + + m_log.Info("[FSDB]: Checking if " + filename + " exists."); + if (File.Exists(filename)) + { + Stopwatch x = new Stopwatch(); + x.Start(); + + XmlTextReader reader = new XmlTextReader(filename); + reader.WhitespaceHandling = WhitespaceHandling.None; + doc.Load(reader); + reader.Close(); + rootNode = doc.FirstChild; + + foreach (XmlNode aPrimNode in rootNode.ChildNodes) + { + xmlList.Add(aPrimNode.OuterXml); + } + + x.Stop(); + TimeToDownload += x.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); + + return xmlList; + } + return null; + } + + public void Initialise(Scene scene, string dir) + { + lock (this) + { + if (m_repodir == null) + m_repodir = dir; + } + lock (m_scenes) + m_scenes.Add(scene.RegionInfo.RegionID, scene); + } + + public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID regionid) + { + SortedDictionary revisionDict = new SortedDictionary(); + + string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; + string[] directories = Directory.GetDirectories(scenedir); + + FileStream fs = null; + StreamReader sr = null; + String logMessage = ""; + String logLocation = ""; + foreach (string revisionDir in directories) + { + try + { + logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; + fs = new FileStream( logLocation, FileMode.Open); + sr = new StreamReader(fs); + logMessage = sr.ReadToEnd(); + sr.Close(); + fs.Close(); + revisionDict.Add(revisionDir, logMessage); + } + catch (Exception) + { + } + } + + return revisionDict; + } + + public int NumOfRegionRev(UUID regionid) + { + string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; + m_log.Info("[FSDB]: Reading scene dir: " + scenedir); + string[] directories = Directory.GetDirectories(scenedir); + return directories.Length; + } + + // Run once and only once. + public void PostInitialise() + { + SetupSerialiser(); + + m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); + CreateDirectory(); + } + + public void SaveRegion(UUID regionid, string regionName, string logMessage) + { + m_log.Info("[FSDB]: ..............................."); + string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; + + m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); + if (!Directory.Exists(scenedir)) + Directory.CreateDirectory(scenedir); + + int newRevisionNum = GetMostRecentRevision(regionid)+1; + string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; + + m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); + if (!Directory.Exists(revisiondir)) + Directory.CreateDirectory(revisiondir); + + try { + Stopwatch x = new Stopwatch(); + x.Start(); + if (m_scenes.ContainsKey(regionid)) + { + m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); + } + x.Stop(); + TimeToSave += x.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); + m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); + } + catch (Exception e) + { + m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); + return; + } + + try { + // Finish by writing log message. + FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); + StreamWriter sw = new StreamWriter(file); + sw.Write(logMessage); + sw.Close(); + } + catch (Exception e) + { + m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); + return; + } + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs new file mode 100644 index 0000000..d24747c --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs @@ -0,0 +1,167 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// GitDatabase.cs +// +// +// + +#endregion Header + +using System; +using System.Collections.Generic; +using System.IO; +using Slash = System.IO.Path; +using System.Reflection; +using System.Xml; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + /// + /// Just a stub :-( + /// + public class GitDatabase : IContentDatabase + { + #region Constructors + + public GitDatabase() + { + } + + #endregion Constructors + + #region Public Methods + + public SceneObjectGroup GetMostRecentObjectRevision(UUID id) + { + return null; + } + + public int GetMostRecentRevision(UUID regionid) + { + return 0; + } + + public SceneObjectGroup GetObjectRevision(UUID id, int revision) + { + return null; + } + + public System.Collections.ArrayList GetObjectsFromRegion(UUID regionid, int revision) + { + return null; + } + + public string GetRegionObjectHeightMap(UUID regionid) + { + return null; + } + + public string GetRegionObjectHeightMap(UUID regionid, int revision) + { + return null; + } + + public string GetRegionObjectXML(UUID regionid) + { + return null; + } + + public string GetRegionObjectXML(UUID regionid, int revision) + { + return null; + } + + public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) + { + return null; + } + + public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) + { + return null; + } + + public bool InRepository(UUID id) + { + return false; + } + + public void Initialise(Scene scene, String dir) + { + } + + public System.Collections.Generic.SortedDictionary ListOfObjectRevisions(UUID id) + { + return null; + } + + public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id) + { + return null; + } + + public int NumOfObjectRev(UUID id) + { + return 0; + } + + public int NumOfRegionRev(UUID regionid) + { + return 0; + } + + public void PostInitialise() + { + } + + public void SaveObject(SceneObjectGroup entity) + { + } + + public void SaveRegion(UUID regionid, string regionName, string logMessage) + { + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs new file mode 100644 index 0000000..7a25fa5 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs @@ -0,0 +1,94 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// IContentDatabase.cs +// User: bongiojp +// +// +// + +#endregion Header + +using System; +using OpenMetaverse; +using OpenSim.Region.Framework.Scenes; +using Nini.Config; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public interface IContentDatabase + { + #region Methods + + /// + /// Returns the most recent revision number of a region. + /// + int GetMostRecentRevision(UUID regionid); + + string GetRegionObjectHeightMap(UUID regionid); + + string GetRegionObjectHeightMap(UUID regionid, int revision); + + /// + /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. + /// + System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid); + + System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision); + + /// + /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. + /// Initialise should be called one for each region to be contained in the database. The directory should be the full path + /// to the repository and will only be defined once, regardless of how many times the method is called. + /// + void Initialise(Scene scene, String dir); + + /// + /// Returns a list of the revision numbers and corresponding log messages for a given region. + /// + System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id); + + /// + /// Returns the total number of revisions saved for a specific region. + /// + int NumOfRegionRev(UUID regionid); + + /// + /// Should be called once after Initialise has been called. + /// + void PostInitialise(); + + /// + /// Saves the Region terrain map and objects within the region as xml to the database. + /// + void SaveRegion(UUID regionid, string regionName, string logMessage); + + #endregion Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs new file mode 100644 index 0000000..63c74e1 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs @@ -0,0 +1,274 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// MetaEntity.cs +// User: bongiojp +// +// TODO: +// Create a physics manager to the meta object if there isn't one or the object knows of no scene but the user wants physics enabled. + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Drawing; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class MetaEntity + { + #region Constants + + public const float INVISIBLE = .95f; + + // Settings for transparency of metaentity + public const float NONE = 0f; + public const float TRANSLUCENT = .5f; + + #endregion Constants + + #region Static Fields + + protected static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. + protected uint m_metaLocalid; + + #endregion Fields + + #region Constructors + + public MetaEntity() + { + } + + /// + /// Makes a new meta entity by copying the given scene object group. + /// The physics boolean is just a stub right now. + /// + public MetaEntity(SceneObjectGroup orig, bool physics) + { + m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false); + Initialize(physics); + } + + /// + /// Takes an XML description of a scene object group and converts it to a meta entity. + /// + public MetaEntity(string objectXML, Scene scene, bool physics) + { + m_Entity = new SceneObjectGroup(objectXML); + m_Entity.SetScene(scene); + Initialize(physics); + } + + #endregion Constructors + + #region Public Properties + + public Dictionary Children + { + get { return m_Entity.Children; } + set { m_Entity.Children = value; } + } + + public uint LocalId + { + get { return m_Entity.LocalId; } + set { m_Entity.LocalId = value; } + } + + public SceneObjectGroup ObjectGroup + { + get { return m_Entity; } + } + + public int PrimCount + { + get { return m_Entity.PrimCount; } + } + + public SceneObjectPart RootPart + { + get { return m_Entity.RootPart; } + } + + public Scene Scene + { + get { return m_Entity.Scene; } + } + + public UUID UUID + { + get { return m_Entity.UUID; } + set { m_Entity.UUID = value; } + } + + #endregion Public Properties + + #region Protected Methods + + // The metaentity objectgroup must have unique localids as well as unique uuids. + // localids are used by the client to refer to parts. + // uuids are sent to the client and back to the server to identify parts on the server side. + /// + /// Changes localids and uuids of m_Entity. + /// + protected void Initialize(bool physics) + { + //make new uuids + Dictionary parts = new Dictionary(); + foreach (SceneObjectPart part in m_Entity.Children.Values) + { + part.ResetIDs(part.LinkNum); + parts.Add(part.UUID, part); + } + + //finalize + m_Entity.RootPart.PhysActor = null; + m_Entity.Children = parts; + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Hides the metaentity from a single client. + /// + public virtual void Hide(IClientAPI client) + { + //This deletes the group without removing from any databases. + //This is important because we are not IN any database. + //m_Entity.FakeDeleteGroup(); + foreach (SceneObjectPart part in m_Entity.Children.Values) + client.SendKillObject(m_Entity.RegionHandle, part.LocalId); + } + + /// + /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. + /// + public virtual void HideFromAll() + { + foreach (SceneObjectPart part in m_Entity.Children.Values) + m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) + { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } + ); + } + + public void SendFullUpdate(IClientAPI client) + { + // Not sure what clientFlags should be but 0 seems to work + SendFullUpdate(client, 0); + } + + public void SendFullUpdate(IClientAPI client, uint clientFlags) + { + m_Entity.SendFullUpdateToClient(client); + } + + public void SendFullUpdateToAll() + { + m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) + { m_Entity.SendFullUpdateToClient(controller); } + ); + } + + /// + /// Makes a single SceneObjectPart see through. + /// + /// + /// A + /// The part to make see through + /// + /// + /// A + /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. + /// + public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) + { + Primitive.TextureEntry tex = null; + Color4 texcolor; + try + { + tex = part.Shape.Textures; + texcolor = new Color4(); + } + catch(Exception) + { + //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); + return; + } + + for (uint i = 0; i < tex.FaceTextures.Length; i++) + { + try { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = transparencyAmount; + tex.FaceTextures[i].RGBA = texcolor; + } + } + catch (Exception) + { + //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); + continue; + } + } + try { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = transparencyAmount; + tex.DefaultTexture.RGBA = texcolor; + part.Shape.TextureEntry = tex.ToBytes(); + } + catch (Exception) + { + //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); + } + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs new file mode 100644 index 0000000..22f09fd --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs @@ -0,0 +1,116 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// PointMetaEntity.cs created with MonoDevelop +// User: bongiojp at 3:03 PM 8/6/2008 +// +// To change standard headers go to Edit->Preferences->Coding->Standard Headers +// + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Drawing; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + public class PointMetaEntity : MetaEntity + { + #region Constructors + + public PointMetaEntity(Scene scene, Vector3 groupPos, float transparency) + : base() + { + CreatePointEntity(scene, UUID.Random(), groupPos); + SetPartTransparency(m_Entity.RootPart, transparency); + } + + public PointMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency) + : base() + { + CreatePointEntity(scene, uuid, groupPos); + SetPartTransparency(m_Entity.RootPart, transparency); + } + + #endregion Constructors + + #region Private Methods + + private void CreatePointEntity(Scene scene, UUID uuid, Vector3 groupPos) + { + SceneObjectGroup x = new SceneObjectGroup(); + SceneObjectPart y = new SceneObjectPart(); + + //Initialize part + y.Name = "Very Small Point"; + y.RegionHandle = scene.RegionInfo.RegionHandle; + y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + y.OwnerID = UUID.Zero; + y.CreatorID = UUID.Zero; + y.LastOwnerID = UUID.Zero; + y.UUID = uuid; + + y.Shape = PrimitiveBaseShape.CreateBox(); + y.Scale = new Vector3(0.01f,0.01f,0.01f); + y.LastOwnerID = UUID.Zero; + y.GroupPosition = groupPos; + y.OffsetPosition = new Vector3(0, 0, 0); + y.RotationOffset = new Quaternion(0,0,0,0); + y.Velocity = new Vector3(0, 0, 0); + y.RotationalVelocity = new Vector3(0, 0, 0); + y.AngularVelocity = new Vector3(0, 0, 0); + y.Acceleration = new Vector3(0, 0, 0); + + y.Flags = 0; + y.TrimPermissions(); + + //Initialize group and add part as root part + x.SetScene(scene); + x.SetRootPart(y); + x.RegionHandle = scene.RegionInfo.RegionHandle; + x.SetScene(scene); + + m_Entity = x; + } + + #endregion Private Methods + } +} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/README b/OpenSim/Region/OptionalModules/ContentManagementSystem/README new file mode 100644 index 0000000..1a69fef --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/README @@ -0,0 +1,52 @@ +This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a +reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/ +directory. + +To compile: nant +To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory. + + +-------------------------------------------------------------------------------------------------------------------- +To build the libgit.so file: + +#Download GIT git repository +$ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git +$ cd git + +#Compile GIT +#Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC) +$ autoconf +$ ./configure +$ CFLAGS="-g -O2 -Wall -c -fPIC" make + +#Copy necessary object files (and some not so necessary) to their own directory for shared object file creation +$ mkdir ../libgit-objects +$ cp builtin*.o ../libgit-objects +$ cp xdiff/*.o ../libgit-objects +$ cp libgit.a ../libgit-objects + +#Remove the main symbol from any object files (like git.o) +$ cd ../libgit-objects +$ strip -N main *.o + +#Uncompress the plumbing objects from archive created by git +$ ar x libgit.a + +#Create shared object file from all objects (including the zlib library) +$ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o + + +#You can also just copy the following commands into a file and run as a script inside the git directory + +make clean +autoconf +./configure +CFLAGS="-g -O2 -Wall -c -fPIC" make +mkdir libgit-objects +cp builtin*.o libgit-objects +cp xdiff/*.o libgit-objects +cp libgit.a libgit-objects +cd libgit-objects +strip -N main *.o +ar x libgit.a +ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs new file mode 100644 index 0000000..8957e8f --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs @@ -0,0 +1,218 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#region Header + +// SceneObjectGroupDiff.cs +// User: bongiojp + +#endregion Header + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; + +using OpenMetaverse; + +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Physics.Manager; + +using log4net; + +namespace OpenSim.Region.OptionalModules.ContentManagement +{ + #region Enumerations + + [Flags] + public enum Diff + { + NONE = 0, + FACECOLOR = 1, + SHAPE = 1<<1, + MATERIAL = 1<<2, + TEXTURE = 1<<3, + SCALE = 1<<4, + POSITION = 1<<5, + OFFSETPOSITION = 1<<6, + ROTATIONOFFSET = 1<<7, + ROTATIONALVELOCITY = 1<<8, + ACCELERATION = 1<<9, + ANGULARVELOCITY = 1<<10, + VELOCITY = 1<<11, + OBJECTOWNER = 1<<12, + PERMISSIONS = 1<<13, + DESCRIPTION = 1<<14, + NAME = 1<<15, + SCRIPT = 1<<16, + CLICKACTION = 1<<17, + PARTICLESYSTEM = 1<<18, + GLOW = 1<<19, + SALEPRICE = 1<<20, + SITNAME = 1<<21, + SITTARGETORIENTATION = 1<<22, + SITTARGETPOSITION = 1<<23, + TEXT = 1<<24, + TOUCHNAME = 1<<25 + } + + #endregion Enumerations + + public static class Difference + { + #region Static Fields + + static float TimeToDiff = 0; +// private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Private Methods + + private static bool AreQuaternionsEquivalent(Quaternion first, Quaternion second) + { + Vector3 firstVector = llRot2Euler(first); + Vector3 secondVector = llRot2Euler(second); + return AreVectorsEquivalent(firstVector, secondVector); + } + + private static bool AreVectorsEquivalent(Vector3 first, Vector3 second) + { + if (TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) + && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) + && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) + ) + return true; + else + return false; + } + + // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs + private static double NormalizeAngle(double angle) + { + angle = angle % (Math.PI * 2); + if (angle < 0) angle = angle + Math.PI * 2; + return angle; + } + + private static int TruncateSignificant(float num, int digits) + { + return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); + // return (int) ((num * (10*digits))/10*digits); + } + + // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs + // Also changed the original function from LSL_Types to LL types + private static Vector3 llRot2Euler(Quaternion r) + { + Quaternion t = new Quaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W); + double m = (t.X + t.Y + t.Z + t.W); + if (m == 0) return new Vector3(); + double n = 2 * (r.Y * r.W + r.X * r.Z); + double p = m * m - n * n; + if (p > 0) + return new Vector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))), + (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), + (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W)))); + else if (n > 0) + return new Vector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); + else + return new Vector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); + } + + #endregion Private Methods + + #region Public Methods + + /// + /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts + /// and returns a Diff bitmask which details what the differences are. + /// + public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) + { + Stopwatch x = new Stopwatch(); + x.Start(); + + Diff result = 0; + + // VECTOR COMPARISONS + if (!AreVectorsEquivalent(first.Acceleration, second.Acceleration)) + result |= Diff.ACCELERATION; + if (!AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) + result |= Diff.POSITION; + if (!AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) + result |= Diff.ANGULARVELOCITY; + if (!AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) + result |= Diff.OFFSETPOSITION; + if (!AreVectorsEquivalent(first.RotationalVelocity, second.RotationalVelocity)) + result |= Diff.ROTATIONALVELOCITY; + if (!AreVectorsEquivalent(first.Scale, second.Scale)) + result |= Diff.SCALE; + if (!AreVectorsEquivalent(first.Velocity, second.Velocity)) + result |= Diff.VELOCITY; + + + // QUATERNION COMPARISONS + if (!AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) + result |= Diff.ROTATIONOFFSET; + + + // MISC COMPARISONS (UUID, Byte) + if (first.ClickAction != second.ClickAction) + result |= Diff.CLICKACTION; + if (first.ObjectOwner != second.ObjectOwner) + result |= Diff.OBJECTOWNER; + + + // STRING COMPARISONS + if (first.Description != second.Description) + result |= Diff.DESCRIPTION; + if (first.Material != second.Material) + result |= Diff.MATERIAL; + if (first.Name != second.Name) + result |= Diff.NAME; + if (first.SitName != second.SitName) + result |= Diff.SITNAME; + if (first.Text != second.Text) + result |= Diff.TEXT; + if (first.TouchName != second.TouchName) + result |= Diff.TOUCHNAME; + + x.Stop(); + TimeToDiff += x.ElapsedMilliseconds; + //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); + + return result; + } + + #endregion Public Methods + } +} diff --git a/OpenSim/Region/OptionalModules/Grid/Interregion/IInterregionModule.cs b/OpenSim/Region/OptionalModules/Grid/Interregion/IInterregionModule.cs new file mode 100644 index 0000000..a2c98a4 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Grid/Interregion/IInterregionModule.cs @@ -0,0 +1,43 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Grid.Interregion +{ + public interface IInterregionModule + { + void RegisterMethod(T e); + bool HasInterface(Location loc); + T RequestInterface(Location loc); + T[] RequestInterface(); + Location GetLocationByDirection(Scene scene, InterregionModule.Direction dir); + void internal_CreateRemotingObjects(); + void RegisterRemoteRegion(string uri); + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Grid/Interregion/InterregionModule.cs b/OpenSim/Region/OptionalModules/Grid/Interregion/InterregionModule.cs new file mode 100644 index 0000000..21df83c --- /dev/null +++ b/OpenSim/Region/OptionalModules/Grid/Interregion/InterregionModule.cs @@ -0,0 +1,199 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Grid.Interregion +{ + public class InterregionModule : IInterregionModule, IRegionModule + { + #region Direction enum + + public enum Direction + { + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest + } + + #endregion + + private readonly Dictionary m_interfaces = new Dictionary(); + private readonly Object m_lockObject = new object(); + private readonly List m_myLocations = new List(); + + private readonly Dictionary m_neighbourInterfaces = new Dictionary(); + private readonly Dictionary m_neighbourRemote = new Dictionary(); + // private IConfigSource m_config; + private const bool m_enabled = false; + + private RemotingObject m_myRemote; + private TcpChannel m_tcpChannel; + private int m_tcpPort = 10101; + + #region IInterregionModule Members + + public void internal_CreateRemotingObjects() + { + lock (m_lockObject) + { + if (m_tcpChannel == null) + { + m_myRemote = new RemotingObject(m_interfaces, m_myLocations.ToArray()); + m_tcpChannel = new TcpChannel(m_tcpPort); + + ChannelServices.RegisterChannel(m_tcpChannel, false); + RemotingServices.Marshal(m_myRemote, "OpenSimRemote2", typeof (RemotingObject)); + } + } + } + + public void RegisterMethod(T e) + { + m_interfaces[typeof (T)] = e; + } + + public bool HasInterface(Location loc) + { + foreach (string val in m_neighbourInterfaces[loc]) + { + if (val == typeof (T).FullName) + { + return true; + } + } + return false; + } + + public T RequestInterface(Location loc) + { + if (m_neighbourRemote.ContainsKey(loc)) + { + return m_neighbourRemote[loc].RequestInterface(); + } + throw new IndexOutOfRangeException("No neighbour availible at that location"); + } + + public T[] RequestInterface() + { + List m_t = new List(); + foreach (RemotingObject remote in m_neighbourRemote.Values) + { + try + { + m_t.Add(remote.RequestInterface()); + } + catch (NotSupportedException) + { + } + } + return m_t.ToArray(); + } + + public Location GetLocationByDirection(Scene scene, Direction dir) + { + return new Location(0, 0); + } + + public void RegisterRemoteRegion(string uri) + { + RegisterRemotingInterface((RemotingObject) Activator.GetObject(typeof (RemotingObject), uri)); + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + m_myLocations.Add(new Location((int) scene.RegionInfo.RegionLocX, + (int) scene.RegionInfo.RegionLocY)); + // m_config = source; + + scene.RegisterModuleInterface(this); + } + + public void PostInitialise() + { + // Commenting out to remove 'unreachable code' warning since m_enabled is never true +// if (m_enabled) +// { +// try +// { +// m_tcpPort = m_config.Configs["Comms"].GetInt("remoting_port", m_tcpPort); +// } +// catch +// { +// } +// +// internal_CreateRemotingObjects(); +// } + } + + public void Close() + { + if (null != m_tcpChannel) + ChannelServices.UnregisterChannel(m_tcpChannel); + } + + public string Name + { + get { return "InterregionModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void RegisterRemotingInterface(RemotingObject remote) + { + Location[] locs = remote.GetLocations(); + string[] interfaces = remote.GetInterfaces(); + foreach (Location loc in locs) + { + m_neighbourInterfaces[loc] = interfaces; + m_neighbourRemote[loc] = remote; + } + } + } +} diff --git a/OpenSim/Region/OptionalModules/Grid/Interregion/RemotingObject.cs b/OpenSim/Region/OptionalModules/Grid/Interregion/RemotingObject.cs new file mode 100644 index 0000000..b09c848 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Grid/Interregion/RemotingObject.cs @@ -0,0 +1,77 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenSim.Framework; + +namespace OpenSim.Region.CoreModules.Grid.Interregion +{ + public class RemotingObject : MarshalByRefObject + { + private readonly Location[] m_coords; + private readonly Dictionary m_interfaces = new Dictionary(); + + public RemotingObject(Dictionary myInterfaces, Location[] coords) + { + m_interfaces = myInterfaces; + m_coords = coords; + } + + public Location[] GetLocations() + { + return (Location[]) m_coords.Clone(); + } + + public string[] GetInterfaces() + { + string[] interfaces = new string[m_interfaces.Count]; + int i = 0; + + foreach (KeyValuePair pair in m_interfaces) + { + interfaces[i++] = pair.Key.FullName; + } + + return interfaces; + } + + /// + /// Returns a registered interface availible to neighbouring regions. + /// + /// The type of interface you wish to request + /// A MarshalByRefObject inherited from this region inheriting the interface requested. + /// All registered interfaces MUST inherit from MarshalByRefObject and use only serialisable types. + public T RequestInterface() + { + if (m_interfaces.ContainsKey(typeof (T))) + return (T) m_interfaces[typeof (T)]; + + throw new NotSupportedException("No such interface registered."); + } + } +} diff --git a/OpenSim/Region/OptionalModules/Python/PythonAPI/Console.cs b/OpenSim/Region/OptionalModules/Python/PythonAPI/Console.cs new file mode 100644 index 0000000..215a9ad --- /dev/null +++ b/OpenSim/Region/OptionalModules/Python/PythonAPI/Console.cs @@ -0,0 +1,48 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using log4net; + +namespace OpenSim.Region.Modules.Python.PythonAPI +{ + class Console + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public void WriteLine(string txt) + { + m_log.Info(txt); + } + + public void WriteLine(string txt, params Object[] e) + { + m_log.Info(String.Format(txt, e)); + } + } +} diff --git a/OpenSim/Region/OptionalModules/Python/PythonModule.cs b/OpenSim/Region/OptionalModules/Python/PythonModule.cs new file mode 100644 index 0000000..5dedac2 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Python/PythonModule.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Security.Policy; +using System.Text; +using IronPython.Hosting; +using log4net; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.Modules.Python +{ + class PythonModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private PythonEngine m_python; + + public void Initialise(Scene scene, IConfigSource source) + { + } + + public void PostInitialise() + { + m_log.Info("[PYTHON] Initialising IronPython engine."); + m_python = new PythonEngine(); + m_python.AddToPath(System.Environment.CurrentDirectory + System.IO.Path.DirectorySeparatorChar + "Python"); + } + + public void Close() + { + } + + public string Name + { + get { return "PythonModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } +} diff --git a/OpenSim/Region/OptionalModules/README b/OpenSim/Region/OptionalModules/README new file mode 100644 index 0000000..0fe7b87 --- /dev/null +++ b/OpenSim/Region/OptionalModules/README @@ -0,0 +1,9 @@ += OpenSim.Region.OptionalModules = + +The modules in this part of the OpenSim source tree are candidates for forge. For the time being, until we have reached consensus on + + (a) what should be core or optional + (b) that we have reached a stable API + (c) how to maintain optional modules + +we will keep these modules in-tree. \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/SvnSerialiser/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/SvnSerialiser/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..165fcea --- /dev/null +++ b/OpenSim/Region/OptionalModules/SvnSerialiser/Properties/AssemblyInfo.cs @@ -0,0 +1,62 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SvnSerialiser")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SvnSerialiser")] +[assembly: AssemblyCopyright("Copyright (c) 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c0893655-0c18-4dd7-8b5b-5f58ab1ec6c7")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs b/OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs new file mode 100644 index 0000000..c4fc584 --- /dev/null +++ b/OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs @@ -0,0 +1,396 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Timers; +using log4net; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Scenes; +using PumaCode.SvnDotNet.AprSharp; +using PumaCode.SvnDotNet.SubversionSharp; +using Slash = System.IO.Path; + +namespace OpenSim.Region.Modules.SvnSerialiser +{ + public class SvnBackupModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private readonly List m_scenes = new List(); + private readonly Timer m_timer = new Timer(); + + private bool m_enabled = false; + private bool m_installBackupOnLoad = false; + private IRegionSerialiserModule m_serialiser; + private bool m_svnAutoSave = false; + private SvnClient m_svnClient; + private string m_svndir = "SVNmodule" + Slash.DirectorySeparatorChar + "repo"; + private string m_svnpass = "password"; + + private TimeSpan m_svnperiod = new TimeSpan(0, 0, 15, 0, 0); + private string m_svnurl = "svn://insert.Your.svn/here/"; + private string m_svnuser = "username"; + + #region SvnModule Core + + /// + /// Exports a specified scene to the SVN repo directory, then commits. + /// + /// The scene to export + public void SaveRegion(Scene scene) + { + List svnfilenames = CreateAndAddExport(scene); + + m_svnClient.Commit3(svnfilenames, true, false); + m_log.Info("[SVNBACKUP]: Region backup successful (" + scene.RegionInfo.RegionName + ")."); + } + + /// + /// Saves all registered scenes to the SVN repo, then commits. + /// + public void SaveAllRegions() + { + List svnfilenames = new List(); + List regions = new List(); + + foreach (Scene scene in m_scenes) + { + svnfilenames.AddRange(CreateAndAddExport(scene)); + regions.Add("'" + scene.RegionInfo.RegionName + "' "); + } + + m_svnClient.Commit3(svnfilenames, true, false); + m_log.Info("[SVNBACKUP]: Server backup successful (" + String.Concat(regions.ToArray()) + ")."); + } + + private List CreateAndAddExport(Scene scene) + { + m_log.Info("[SVNBACKUP]: Saving a region to SVN with name " + scene.RegionInfo.RegionName); + + List filenames = m_serialiser.SerialiseRegion(scene, m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID + Slash.DirectorySeparatorChar); + + try + { + m_svnClient.Add3(m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID, true, false, false); + } + catch (SvnException) + { + } + + List svnfilenames = new List(); + foreach (string filename in filenames) + svnfilenames.Add(m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID + Slash.DirectorySeparatorChar + filename); + svnfilenames.Add(m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID); + + return svnfilenames; + } + + public void LoadRegion(Scene scene) + { + IRegionSerialiserModule serialiser = scene.RequestModuleInterface(); + if (serialiser != null) + { + serialiser.LoadPrimsFromXml2( + scene, + m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID + + Slash.DirectorySeparatorChar + "objects.xml"); + + scene.RequestModuleInterface().LoadFromFile( + m_svndir + Slash.DirectorySeparatorChar + scene.RegionInfo.RegionID + + Slash.DirectorySeparatorChar + "heightmap.r32"); + + m_log.Info("[SVNBACKUP]: Region load successful (" + scene.RegionInfo.RegionName + ")."); + } + else + { + m_log.ErrorFormat( + "[SVNBACKUP]: Region load of {0} failed - no serialisation module available", + scene.RegionInfo.RegionName); + } + } + + private void CheckoutSvn() + { + m_svnClient.Checkout2(m_svnurl, m_svndir, Svn.Revision.Head, Svn.Revision.Head, true, false); + } + + private void CheckoutSvn(SvnRevision revision) + { + m_svnClient.Checkout2(m_svnurl, m_svndir, revision, revision, true, false); + } + + // private void CheckoutSvnPartial(string subdir) + // { + // if (!Directory.Exists(m_svndir + Slash.DirectorySeparatorChar + subdir)) + // Directory.CreateDirectory(m_svndir + Slash.DirectorySeparatorChar + subdir); + + // m_svnClient.Checkout2(m_svnurl + "/" + subdir, m_svndir, Svn.Revision.Head, Svn.Revision.Head, true, false); + // } + + // private void CheckoutSvnPartial(string subdir, SvnRevision revision) + // { + // if (!Directory.Exists(m_svndir + Slash.DirectorySeparatorChar + subdir)) + // Directory.CreateDirectory(m_svndir + Slash.DirectorySeparatorChar + subdir); + + // m_svnClient.Checkout2(m_svnurl + "/" + subdir, m_svndir, revision, revision, true, false); + // } + + #endregion + + #region SvnDotNet Callbacks + + private SvnError SimpleAuth(out SvnAuthCredSimple svnCredentials, IntPtr baton, + AprString realm, AprString username, bool maySave, AprPool pool) + { + svnCredentials = SvnAuthCredSimple.Alloc(pool); + svnCredentials.Username = new AprString(m_svnuser, pool); + svnCredentials.Password = new AprString(m_svnpass, pool); + svnCredentials.MaySave = false; + return SvnError.NoError; + } + + private SvnError GetCommitLogCallback(out AprString logMessage, out SvnPath tmpFile, AprArray commitItems, IntPtr baton, AprPool pool) + { + if (!commitItems.IsNull) + { + foreach (SvnClientCommitItem2 item in commitItems) + { + m_log.Debug("[SVNBACKUP]: ... " + Path.GetFileName(item.Path.ToString()) + " (" + item.Kind.ToString() + ") r" + item.Revision.ToString()); + } + } + + string msg = "Region Backup (" + System.Environment.MachineName + " at " + DateTime.UtcNow + " UTC)"; + + m_log.Debug("[SVNBACKUP]: Saved with message: " + msg); + + logMessage = new AprString(msg, pool); + tmpFile = new SvnPath(pool); + + return (SvnError.NoError); + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource source) + { + try + { + if (!source.Configs["SVN"].GetBoolean("Enabled", false)) + return; + + m_enabled = true; + + m_svndir = source.Configs["SVN"].GetString("Directory", m_svndir); + m_svnurl = source.Configs["SVN"].GetString("URL", m_svnurl); + m_svnuser = source.Configs["SVN"].GetString("Username", m_svnuser); + m_svnpass = source.Configs["SVN"].GetString("Password", m_svnpass); + m_installBackupOnLoad = source.Configs["SVN"].GetBoolean("ImportOnStartup", m_installBackupOnLoad); + m_svnAutoSave = source.Configs["SVN"].GetBoolean("Autosave", m_svnAutoSave); + m_svnperiod = new TimeSpan(0, source.Configs["SVN"].GetInt("AutosavePeriod", (int) m_svnperiod.TotalMinutes), 0); + } + catch (Exception) + { + } + + lock (m_scenes) + { + m_scenes.Add(scene); + } + //Only register it once, to prevent command being executed x*region times + if (m_scenes.Count == 1) + { + scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; + } + } + + public void PostInitialise() + { + if (m_enabled == false) + return; + + if (m_svnAutoSave) + { + m_timer.Interval = m_svnperiod.TotalMilliseconds; + m_timer.Elapsed += m_timer_Elapsed; + m_timer.AutoReset = true; + m_timer.Start(); + } + + m_log.Info("[SVNBACKUP]: Connecting to SVN server " + m_svnurl + " ..."); + SetupSvnProvider(); + + m_log.Info("[SVNBACKUP]: Creating repository in " + m_svndir + "."); + CreateSvnDirectory(); + CheckoutSvn(); + SetupSerialiser(); + + if (m_installBackupOnLoad) + { + m_log.Info("[SVNBACKUP]: Importing latest SVN revision to scenes..."); + foreach (Scene scene in m_scenes) + { + LoadRegion(scene); + } + } + } + + public void Close() + { + } + + public string Name + { + get { return "SvnBackupModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void EventManager_OnPluginConsole(string[] args) + { + if (args[0] == "svn" && args[1] == "save") + { + SaveAllRegions(); + } + if (args.Length == 2) + { + if (args[0] == "svn" && args[1] == "load") + { + LoadAllScenes(); + } + } + if (args.Length == 3) + { + if (args[0] == "svn" && args[1] == "load") + { + LoadAllScenes(Int32.Parse(args[2])); + } + } + if (args.Length == 3) + { + if (args[0] == "svn" && args[1] == "load-region") + { + LoadScene(args[2]); + } + } + if (args.Length == 4) + { + if (args[0] == "svn" && args[1] == "load-region") + { + LoadScene(args[2], Int32.Parse(args[3])); + } + } + } + + public void LoadScene(string name) + { + CheckoutSvn(); + + foreach (Scene scene in m_scenes) + { + if (scene.RegionInfo.RegionName.ToLower().Equals(name.ToLower())) + { + LoadRegion(scene); + return; + } + } + m_log.Warn("[SVNBACKUP]: No region loaded - unable to find matching name."); + } + + public void LoadScene(string name, int revision) + { + CheckoutSvn(new SvnRevision(revision)); + + foreach (Scene scene in m_scenes) + { + if (scene.RegionInfo.RegionName.ToLower().Equals(name.ToLower())) + { + LoadRegion(scene); + return; + } + } + m_log.Warn("[SVNBACKUP]: No region loaded - unable to find matching name."); + } + + public void LoadAllScenes() + { + CheckoutSvn(); + + foreach (Scene scene in m_scenes) + { + LoadRegion(scene); + } + } + + public void LoadAllScenes(int revision) + { + CheckoutSvn(new SvnRevision(revision)); + + foreach (Scene scene in m_scenes) + { + LoadRegion(scene); + } + } + + private void m_timer_Elapsed(object sender, ElapsedEventArgs e) + { + SaveAllRegions(); + } + + private void SetupSerialiser() + { + if (m_scenes.Count > 0) + m_serialiser = m_scenes[0].RequestModuleInterface(); + } + + private void SetupSvnProvider() + { + m_svnClient = new SvnClient(); + m_svnClient.AddUsernameProvider(); + m_svnClient.AddPromptProvider(new SvnAuthProviderObject.SimplePrompt(SimpleAuth), IntPtr.Zero, 2); + m_svnClient.OpenAuth(); + m_svnClient.Context.LogMsgFunc2 = new SvnDelegate(new SvnClient.GetCommitLog2(GetCommitLogCallback)); + } + + private void CreateSvnDirectory() + { + if (!Directory.Exists(m_svndir)) + Directory.CreateDirectory(m_svndir); + } + } +} diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs new file mode 100644 index 0000000..3ba8a97 --- /dev/null +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -0,0 +1,1060 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.World.NPC +{ + public class NPCAvatar : IClientAPI + { + private readonly string m_firstname; + private readonly string m_lastname; + private readonly Vector3 m_startPos; + private readonly UUID m_uuid = UUID.Random(); + private readonly Scene m_scene; + + + public NPCAvatar(string firstname, string lastname, Vector3 position, Scene scene) + { + m_firstname = firstname; + m_lastname = lastname; + m_startPos = position; + m_scene = scene; + } + + public IScene Scene + { + get { return m_scene; } + } + + public void Say(string message) + { + SendOnChatFromClient(message, ChatTypeEnum.Say); + } + + public void Shout(string message) + { + SendOnChatFromClient(message, ChatTypeEnum.Shout); + } + + public void Whisper(string message) + { + SendOnChatFromClient(message, ChatTypeEnum.Whisper); + } + + public void Broadcast(string message) + { + SendOnChatFromClient(message, ChatTypeEnum.Broadcast); + } + + public void GiveMoney(UUID target, int amount) + { + OnMoneyTransferRequest(m_uuid, target, amount, 1, "Payment"); + } + + public void InstantMessage(UUID target, string message) + { + OnInstantMessage(this, new GridInstantMessage(m_scene, + m_uuid, m_firstname + " " + m_lastname, + target, 0, false, message, + UUID.Zero, false, Position, new byte[0])); + } + + public void SendAgentOffline(UUID[] agentIDs) + { + + } + + public void SendAgentOnline(UUID[] agentIDs) + { + + } + public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, + Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) + { + + } + + public void SendAdminResponse(UUID Token, uint AdminLevel) + { + + } + + public void SendGroupMembership(GroupMembershipData[] GroupMembership) + { + + } + + public UUID GetDefaultAnimation(string name) + { + return UUID.Zero; + } + + public Vector3 Position + { + get { return m_scene.Entities[m_uuid].AbsolutePosition; } + set { m_scene.Entities[m_uuid].AbsolutePosition = value; } + } + + public bool SendLogoutPacketWhenClosing + { + set { } + } + + #region Internal Functions + + private void SendOnChatFromClient(string message, ChatTypeEnum chatType) + { + OSChatMessage chatFromClient = new OSChatMessage(); + chatFromClient.Channel = 0; + chatFromClient.From = Name; + chatFromClient.Message = message; + chatFromClient.Position = StartPos; + chatFromClient.Scene = m_scene; + chatFromClient.Sender = this; + chatFromClient.SenderUUID = AgentId; + chatFromClient.Type = chatType; + + OnChatFromClient(this, chatFromClient); + } + + #endregion + + #region Event Definitions IGNORE + +// disable warning: public events constituting public API +#pragma warning disable 67 + public event Action OnLogout; + public event ObjectPermissions OnObjectPermissions; + + public event MoneyTransferRequest OnMoneyTransferRequest; + public event ParcelBuy OnParcelBuy; + public event Action OnConnectionClosed; + public event GenericMessage OnGenericMessage; + public event ImprovedInstantMessage OnInstantMessage; + public event ChatMessage OnChatFromClient; + public event TextureRequest OnRequestTexture; + public event RezObject OnRezObject; + public event ModifyTerrain OnModifyTerrain; + public event SetAppearance OnSetAppearance; + public event AvatarNowWearing OnAvatarNowWearing; + public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; + public event UUIDNameRequest OnDetachAttachmentIntoInv; + public event ObjectAttach OnObjectAttach; + public event ObjectDeselect OnObjectDetach; + public event ObjectDrop OnObjectDrop; + public event StartAnim OnStartAnim; + public event StopAnim OnStopAnim; + public event LinkObjects OnLinkObjects; + public event DelinkObjects OnDelinkObjects; + public event RequestMapBlocks OnRequestMapBlocks; + public event RequestMapName OnMapNameRequest; + public event TeleportLocationRequest OnTeleportLocationRequest; + public event TeleportLandmarkRequest OnTeleportLandmarkRequest; + public event DisconnectUser OnDisconnectUser; + public event RequestAvatarProperties OnRequestAvatarProperties; + public event SetAlwaysRun OnSetAlwaysRun; + + public event DeRezObject OnDeRezObject; + public event Action OnRegionHandShakeReply; + public event GenericCall2 OnRequestWearables; + public event GenericCall2 OnCompleteMovementToRegion; + public event UpdateAgent OnAgentUpdate; + public event AgentRequestSit OnAgentRequestSit; + public event AgentSit OnAgentSit; + public event AvatarPickerRequest OnAvatarPickerRequest; + public event Action OnRequestAvatarsData; + public event AddNewPrim OnAddPrim; + public event RequestGodlikePowers OnRequestGodlikePowers; + public event GodKickUser OnGodKickUser; + public event ObjectDuplicate OnObjectDuplicate; + public event GrabObject OnGrabObject; + public event ObjectSelect OnDeGrabObject; + public event MoveObject OnGrabUpdate; + public event ViewerEffectEventHandler OnViewerEffect; + + public event FetchInventory OnAgentDataUpdateRequest; + public event TeleportLocationRequest OnSetStartLocationRequest; + + public event UpdateShape OnUpdatePrimShape; + public event ObjectExtraParams OnUpdateExtraParams; + public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; + public event ObjectSelect OnObjectSelect; + public event GenericCall7 OnObjectDescription; + public event GenericCall7 OnObjectName; + public event GenericCall7 OnObjectClickAction; + public event GenericCall7 OnObjectMaterial; + public event UpdatePrimFlags OnUpdatePrimFlags; + public event UpdatePrimTexture OnUpdatePrimTexture; + public event UpdateVector OnUpdatePrimGroupPosition; + public event UpdateVector OnUpdatePrimSinglePosition; + public event UpdatePrimRotation OnUpdatePrimGroupRotation; + public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; + public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; + public event UpdateVector OnUpdatePrimScale; + public event UpdateVector OnUpdatePrimGroupScale; + public event StatusChange OnChildAgentStatus; + public event GenericCall2 OnStopMovement; + public event Action OnRemoveAvatar; + + public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event CreateInventoryFolder OnCreateNewInventoryFolder; + public event UpdateInventoryFolder OnUpdateInventoryFolder; + public event MoveInventoryFolder OnMoveInventoryFolder; + public event RemoveInventoryFolder OnRemoveInventoryFolder; + public event RemoveInventoryItem OnRemoveInventoryItem; + public event FetchInventoryDescendents OnFetchInventoryDescendents; + public event PurgeInventoryDescendents OnPurgeInventoryDescendents; + public event FetchInventory OnFetchInventory; + public event RequestTaskInventory OnRequestTaskInventory; + public event UpdateInventoryItem OnUpdateInventoryItem; + public event CopyInventoryItem OnCopyInventoryItem; + public event MoveInventoryItem OnMoveInventoryItem; + public event UDPAssetUploadRequest OnAssetUploadRequest; + public event XferReceive OnXferReceive; + public event RequestXfer OnRequestXfer; + public event AbortXfer OnAbortXfer; + public event ConfirmXfer OnConfirmXfer; + public event RezScript OnRezScript; + public event UpdateTaskInventory OnUpdateTaskInventory; + public event MoveTaskInventory OnMoveTaskItem; + public event RemoveTaskInventory OnRemoveTaskItem; + public event RequestAsset OnRequestAsset; + + public event UUIDNameRequest OnNameFromUUIDRequest; + public event UUIDNameRequest OnUUIDGroupNameRequest; + + public event ParcelPropertiesRequest OnParcelPropertiesRequest; + public event ParcelDivideRequest OnParcelDivideRequest; + public event ParcelJoinRequest OnParcelJoinRequest; + public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + public event ParcelAbandonRequest OnParcelAbandonRequest; + public event ParcelGodForceOwner OnParcelGodForceOwner; + public event ParcelReclaim OnParcelReclaim; + public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest; + public event ParcelAccessListRequest OnParcelAccessListRequest; + public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; + public event ParcelSelectObjects OnParcelSelectObjects; + public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; + public event ObjectDeselect OnObjectDeselect; + public event RegionInfoRequest OnRegionInfoRequest; + public event EstateCovenantRequest OnEstateCovenantRequest; + public event RequestTerrain OnRequestTerrain; + public event RequestTerrain OnUploadTerrain; + public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; + + public event FriendActionDelegate OnApproveFriendRequest; + public event FriendActionDelegate OnDenyFriendRequest; + public event FriendshipTermination OnTerminateFriendship; + + public event EconomyDataRequest OnEconomyDataRequest; + public event MoneyBalanceRequest OnMoneyBalanceRequest; + public event UpdateAvatarProperties OnUpdateAvatarProperties; + + public event ObjectIncludeInSearch OnObjectIncludeInSearch; + public event UUIDNameRequest OnTeleportHomeRequest; + + public event ScriptAnswer OnScriptAnswer; + public event RequestPayPrice OnRequestPayPrice; + public event ObjectSaleInfo OnObjectSaleInfo; + public event ObjectBuy OnObjectBuy; + public event BuyObjectInventory OnBuyObjectInventory; + public event AgentSit OnUndo; + + public event ForceReleaseControls OnForceReleaseControls; + public event GodLandStatRequest OnLandStatRequest; + public event RequestObjectPropertiesFamily OnObjectGroupRequest; + + public event DetailedEstateDataRequest OnDetailedEstateDataRequest; + public event SetEstateFlagsRequest OnSetEstateFlagsRequest; + public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; + public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; + public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; + public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; + public event SetRegionTerrainSettings OnSetRegionTerrainSettings; + public event BakeTerrain OnBakeTerrain; + public event EstateRestartSimRequest OnEstateRestartSimRequest; + public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; + public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; + public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest; + public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest; + public event EstateDebugRegionRequest OnEstateDebugRegionRequest; + public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; + public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; + public event EstateChangeInfo OnEstateChangeInfo; + public event ScriptReset OnScriptReset; + public event GetScriptRunning OnGetScriptRunning; + public event SetScriptRunning OnSetScriptRunning; + public event UpdateVector OnAutoPilotGo; + + public event TerrainUnacked OnUnackedTerrain; + + public event RegionHandleRequest OnRegionHandleRequest; + public event ParcelInfoRequest OnParcelInfoRequest; + + public event ActivateGesture OnActivateGesture; + public event DeactivateGesture OnDeactivateGesture; + public event ObjectOwner OnObjectOwner; + + public event DirPlacesQuery OnDirPlacesQuery; + public event DirFindQuery OnDirFindQuery; + public event DirLandQuery OnDirLandQuery; + public event DirPopularQuery OnDirPopularQuery; + public event DirClassifiedQuery OnDirClassifiedQuery; + public event EventInfoRequest OnEventInfoRequest; + public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; + + public event MapItemRequest OnMapItemRequest; + + public event OfferCallingCard OnOfferCallingCard; + public event AcceptCallingCard OnAcceptCallingCard; + public event DeclineCallingCard OnDeclineCallingCard; + public event SoundTrigger OnSoundTrigger; + + public event StartLure OnStartLure; + public event TeleportLureRequest OnTeleportLureRequest; + public event NetworkStats OnNetworkStatsUpdate; + + public event ClassifiedInfoRequest OnClassifiedInfoRequest; + public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; + public event ClassifiedDelete OnClassifiedDelete; + public event ClassifiedDelete OnClassifiedGodDelete; + + public event EventNotificationAddRequest OnEventNotificationAddRequest; + public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; + public event EventGodDelete OnEventGodDelete; + + public event ParcelDwellRequest OnParcelDwellRequest; + + public event UserInfoRequest OnUserInfoRequest; + public event UpdateUserInfo OnUpdateUserInfo; + +#pragma warning restore 67 + + #endregion + + public void ActivateGesture(UUID assetId, UUID gestureId) + { + } + public void DeactivateGesture(UUID assetId, UUID gestureId) + { + } + + #region Overrriden Methods IGNORE + + public virtual Vector3 StartPos + { + get { return m_startPos; } + set { } + } + + public virtual UUID AgentId + { + get { return m_uuid; } + } + + public UUID SessionId + { + get { return UUID.Zero; } + } + + public UUID SecureSessionId + { + get { return UUID.Zero; } + } + + public virtual string FirstName + { + get { return m_firstname; } + } + + public virtual string LastName + { + get { return m_lastname; } + } + + public virtual String Name + { + get { return FirstName + " " + LastName; } + } + + public bool IsActive + { + get { return true; } + set { } + } + + public UUID ActiveGroupId + { + get { return UUID.Zero; } + } + + public string ActiveGroupName + { + get { return String.Empty; } + } + + public ulong ActiveGroupPowers + { + get { return 0; } + } + + public bool IsGroupMember(UUID groupID) + { + return false; + } + + public ulong GetGroupPowers(UUID groupID) + { + return 0; + } + + public virtual int NextAnimationSequenceNumber + { + get { return 1; } + } + + public virtual void SendWearables(AvatarWearable[] wearables, int serial) + { + } + + public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) + { + } + + public virtual void Kick(string message) + { + } + + public virtual void SendStartPingCheck(byte seq) + { + } + + public virtual void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List Data) + { + } + + public virtual void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle) + { + + } + + public virtual void SendKillObject(ulong regionHandle, uint localID) + { + } + + public virtual void SetChildAgentThrottle(byte[] throttle) + { + } + public byte[] GetThrottlesPacked(float multiplier) + { + return new byte[0]; + } + + + public virtual void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId) + { + } + + public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) + { + } + + public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) + { + } + + public void SendInstantMessage(UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, uint timeStamp) + { + + } + + public void SendInstantMessage(UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, uint timeStamp, UUID transationID, bool fromGroup, byte[] binaryBucket) + { + + } + + public void SendGenericMessage(string method, List message) + { + + } + + public virtual void SendLayerData(float[] map) + { + } + + public virtual void SendLayerData(int px, int py, float[] map) + { + } + public virtual void SendLayerData(int px, int py, float[] map, bool track) + { + } + + public virtual void SendWindData(Vector2[] windSpeeds) { } + + public virtual void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) + { + } + + public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint) + { + } + + public virtual AgentCircuitData RequestClientInfo() + { + return new AgentCircuitData(); + } + + public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, + IPEndPoint newRegionExternalEndPoint, string capsURL) + { + } + + public virtual void SendMapBlock(List mapBlocks, uint flag) + { + } + + public virtual void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags) + { + } + + public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, + uint locationID, uint flags, string capsURL) + { + } + + public virtual void SendTeleportFailed(string reason) + { + } + + public virtual void SendTeleportLocationStart() + { + } + + public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance) + { + } + + public virtual void SendPayPrice(UUID objectID, int[] payPrice) + { + } + + public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, + uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) + { + } + + public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, + Vector3 position, Vector3 velocity, Quaternion rotation) + { + } + + public virtual void SendCoarseLocationUpdate(List CoarseLocations) + { + } + + public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) + { + } + + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string msg, UUID textureID, int ch, string[] buttonlabels) + { + } + + public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, + PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, + Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, + UUID objectID, UUID ownerID, string text, byte[] color, + uint parentID, + byte[] particleSystem, byte clickAction, byte material) + { + } + public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, + PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, + Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, + UUID objectID, UUID ownerID, string text, byte[] color, + uint parentID, + byte[] particleSystem, byte clickAction, byte material, byte[] textureanimation, + bool attachment, uint AttachmentPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius) + { + } + public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, + Vector3 position, Quaternion rotation, Vector3 velocity, + Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) + { + } + + public virtual void SendInventoryFolderDetails(UUID ownerID, UUID folderID, + List items, + List folders, + bool fetchFolders, + bool fetchItems) + { + } + + public virtual void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item) + { + } + + public virtual void SendInventoryItemCreateUpdate(InventoryItemBase Item) + { + } + + public virtual void SendRemoveInventoryItem(UUID itemID) + { + } + + /// IClientAPI.SendBulkUpdateInventory(InventoryItemBase) + public virtual void SendBulkUpdateInventory(InventoryItemBase item) + { + } + + public virtual void SendBulkUpdateInventory(InventoryFolderBase folderBase) + {} + + public void SendTakeControls(int controls, bool passToAgent, bool TakeControls) + { + } + + public virtual void SendTaskInventory(UUID taskID, short serial, byte[] fileName) + { + } + + public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data) + { + } + + public virtual void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, + int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, + int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, + int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) + { + + } + public virtual void SendNameReply(UUID profileId, string firstname, string lastname) + { + } + + public virtual void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID) + { + } + + public virtual void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain, + byte flags) + { + } + + public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) + { + } + + public void SendAttachedSoundGainChange(UUID objectID, float gain) + { + + } + + public void SendAlertMessage(string message) + { + } + + public void SendAgentAlertMessage(string message, bool modal) + { + } + + public void SendSystemAlertMessage(string message) + { + } + + public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, + string url) + { + } + + public virtual void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) + { + if (OnRegionHandShakeReply != null) + { + OnRegionHandShakeReply(this); + } + + if (OnCompleteMovementToRegion != null) + { + OnCompleteMovementToRegion(); + } + } + public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) + { + } + + public void SendConfirmXfer(ulong xferID, uint PacketID) + { + } + + public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) + { + } + + public void SendInitiateDownload(string simFileName, string clientFileName) + { + } + + public void SendImageFirstPart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) + { + } + + public void SendImageNotFound(UUID imageid) + { + } + + public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) + { + } + + public void SendShutdownConnectionNotice() + { + } + + public void SendSimStats(SimStats stats) + { + } + + public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, + uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, + uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, + UUID LastOwnerID, string ObjectName, string Description) + { + } + + public void SendObjectPropertiesReply(UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, + UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, + UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, + string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, + uint BaseMask, byte saleType, int salePrice) + { + } + + public bool AddMoney(int debit) + { + return false; + } + + public void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong time, uint dlen, uint ylen, float phase) + { + } + + public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks) + { + } + + public void SendViewerTime(int phase) + { + } + + public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, + string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL, + UUID partnerID) + { + } + + public void SendAsset(AssetRequestToClient req) + { + } + + public void SendTexture(AssetBase TextureAsset) + { + } + + public void SetDebugPacketLevel(int newDebug) + { + } + + public void InPacket(object NewPack) + { + } + + public void ProcessInPacket(Packet NewPack) + { + } + + public void Close(bool ShutdownCircuit) + { + } + + public void Start() + { + } + + public void Stop() + { + } + + private uint m_circuitCode; + + public uint CircuitCode + { + get { return m_circuitCode; } + set { m_circuitCode = value; } + } + + public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) + { + + } + public void SendLogoutPacket() + { + } + + public void Terminate() + { + } + + public ClientInfo GetClientInfo() + { + return null; + } + + public void SetClientInfo(ClientInfo info) + { + } + + public void SendScriptQuestion(UUID objectID, string taskName, string ownerName, UUID itemID, int question) + { + } + public void SendHealth(float health) + { + } + + public void SendEstateManagersList(UUID invoice, UUID[] EstateManagers, uint estateID) + { + } + + public void SendBannedUserList(UUID invoice, EstateBan[] banlist, uint estateID) + { + } + + public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) + { + } + public void SendEstateCovenantInformation(UUID covenant) + { + } + public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) + { + } + + public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor,int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) + { + } + public void SendLandAccessListData(List avatars, uint accessFlag, int localLandID) + { + } + public void SendForceClientSelectObjects(List objectIDs) + { + } + public void SendLandObjectOwners(Dictionary ownersAndCount) + { + } + public void SendLandParcelOverlay(byte[] data, int sequence_id) + { + } + + public void SendGroupNameReply(UUID groupLLUID, string GroupName) + { + } + + public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) + { + } + + public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) + { + } + #endregion + + + public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) + { + } + + public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, + byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight, + byte mediaLoop) + { + } + + public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) + { + } + + public void SendClearFollowCamProperties (UUID objectID) + { + } + + public void SendRegionHandle (UUID regoinID, ulong handle) + { + } + + public void SendParcelInfo (RegionInfo info, LandData land, UUID parcelID, uint x, uint y) + { + } + + public void SetClientOption(string option, string value) + { + } + + public string GetClientOption(string option) + { + return string.Empty; + } + + public void SendScriptTeleportRequest (string objName, string simName, Vector3 pos, Vector3 lookAt) + { + } + + public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) + { + } + + public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) + { + } + + public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) + { + } + + public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) + { + } + + public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) + { + } + + public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) + { + } + + public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) + { + } + + public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) + { + } + + public void KillEndDone() + { + } + + public void SendEventInfoReply (EventData info) + { + } + + public void SendOfferCallingCard (UUID destID, UUID transactionID) + { + } + + public void SendAcceptCallingCard (UUID transactionID) + { + } + + public void SendDeclineCallingCard (UUID transactionID) + { + } + + public void SendJoinGroupReply(UUID groupID, bool success) + { + } + + public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success) + { + } + + public void SendLeaveGroupReply(UUID groupID, bool success) + { + } + + public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) + { + } + + public void SendTerminateFriend(UUID exFriendID) + { + } + + #region IClientAPI Members + + + public bool AddGenericPacketHandler(string MethodName, GenericMessage handler) + { + throw new NotImplementedException(); + } + + public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) + { + } + + public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) + { + } + + public void SendAgentDropGroup(UUID groupID) + { + } + + public void SendAvatarNotesReply(UUID targetID, string text) + { + } + + public void SendAvatarPicksReply(UUID targetID, Dictionary picks) + { + } + + public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) + { + } + + public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) + { + } + + public void SendUserInfoReply(bool imViaEmail, bool visible, string email) + { + } + + #endregion + } +} diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs new file mode 100644 index 0000000..9dace33 --- /dev/null +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -0,0 +1,68 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.World.NPC +{ + public class NPCModule : IRegionModule + { + // private const bool m_enabled = false; + + public void Initialise(Scene scene, IConfigSource source) + { + // if (m_enabled) + // { + // NPCAvatar testAvatar = new NPCAvatar("Jack", "NPC", new Vector3(128, 128, 40), scene); + // NPCAvatar testAvatar2 = new NPCAvatar("Jill", "NPC", new Vector3(136, 128, 40), scene); + // scene.AddNewClient(testAvatar, false); + // scene.AddNewClient(testAvatar2, false); + // } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "NPCModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } +} diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs new file mode 100644 index 0000000..94ebcac --- /dev/null +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs @@ -0,0 +1,304 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Timers; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.World.TreePopulator +{ + /// + /// Version 2.0 - Very hacky compared to the original. Will fix original and release as 0.3 later. + /// + public class TreePopulatorModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + + public double m_tree_density = 50.0; // Aim for this many per region + public double m_tree_updates = 1000.0; // MS between updates + private bool m_active_trees = false; + private List m_trees; + Timer CalculateTrees; + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + try + { + m_tree_density = config.Configs["Trees"].GetDouble("tree_density", m_tree_density); + m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees); + } + catch (Exception) + { + } + + m_trees = new List(); + m_scene = scene; + + m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; + + if (m_active_trees) + activeizeTreeze(true); + + m_log.Debug("[TREES]: Initialised tree module"); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "TreePopulatorModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + private void EventManager_OnPluginConsole(string[] args) + { + if (args.Length == 1) + { + if (args[0] == "tree") + { + UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (uuid == UUID.Zero) + uuid = m_scene.RegionInfo.MasterAvatarAssignedUUID; + m_log.Debug("[TREES]: New tree planting"); + CreateTree(uuid, new Vector3(128.0f, 128.0f, 0.0f)); + + } + } + + if (args.Length == 2 || args.Length == 3) + { + if (args[1] == "active") + { + if (args.Length >= 3) + { + if (args[2] == "true" && !m_active_trees) + { + m_active_trees = true; + activeizeTreeze(m_active_trees); + m_log.Info("[TREES]: Activizing Trees"); + } + if (args[2] == "false" && m_active_trees) + { + m_active_trees = false; + activeizeTreeze(m_active_trees); + m_log.Info("[TREES]: Trees no longer Active, for now..."); + } + } + else + { + m_log.Info("[TREES]: When setting the tree module active via the console, you must specify true or false"); + } + } + } + + } + + private void activeizeTreeze(bool activeYN) + { + if (activeYN) + { + CalculateTrees = new Timer(m_tree_updates); + CalculateTrees.Elapsed += CalculateTrees_Elapsed; + CalculateTrees.Start(); + } + else + { + CalculateTrees.Stop(); + } + } + + private void growTrees() + { + foreach (UUID tree in m_trees) + { + if (m_scene.Entities.ContainsKey(tree)) + { + SceneObjectPart s_tree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart; + + // 100 seconds to grow 1m + s_tree.Scale += new Vector3(0.1f, 0.1f, 0.1f); + s_tree.SendFullUpdateToAllClients(); + //s_tree.ScheduleTerseUpdate(); + } + else + { + m_trees.Remove(tree); + } + } + } + + private void seedTrees() + { + foreach (UUID tree in m_trees) + { + if (m_scene.Entities.ContainsKey(tree)) + { + SceneObjectPart s_tree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart; + + if (s_tree.Scale.X > 0.5) + { + if (Util.RandomClass.NextDouble() > 0.75) + { + SpawnChild(s_tree); + } + } + } + else + { + m_trees.Remove(tree); + } + } + } + + private void killTrees() + { + foreach (UUID tree in m_trees) + { + double killLikelyhood = 0.0; + + if (m_scene.Entities.ContainsKey(tree)) + { + SceneObjectPart selectedTree = ((SceneObjectGroup) m_scene.Entities[tree]).RootPart; + double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) + + Math.Pow(selectedTree.Scale.Y, 2) + + Math.Pow(selectedTree.Scale.Z, 2)); + + foreach (UUID picktree in m_trees) + { + if (picktree != tree) + { + SceneObjectPart pickedTree = ((SceneObjectGroup) m_scene.Entities[picktree]).RootPart; + + double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) + + Math.Pow(pickedTree.Scale.Y, 2) + + Math.Pow(pickedTree.Scale.Z, 2)); + + double pickedTreeDistance = Math.Sqrt(Math.Pow(Math.Abs(pickedTree.AbsolutePosition.X - selectedTree.AbsolutePosition.X), 2) + + Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Y - selectedTree.AbsolutePosition.Y), 2) + + Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Z - selectedTree.AbsolutePosition.Z), 2)); + + killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1; + } + } + + if (Util.RandomClass.NextDouble() < killLikelyhood) + { + m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); + m_trees.Remove(selectedTree.ParentGroup.UUID); + + m_scene.ForEachClient(delegate(IClientAPI controller) + { + controller.SendKillObject(m_scene.RegionInfo.RegionHandle, + selectedTree.LocalId); + }); + + break; + } + selectedTree.SetText(killLikelyhood.ToString(), new Vector3(1.0f, 1.0f, 1.0f), 1.0); + } + else + { + m_trees.Remove(tree); + } + } + } + + private void SpawnChild(SceneObjectPart s_tree) + { + Vector3 position = new Vector3(); + + position.X = s_tree.AbsolutePosition.X + (1 * (-1 * Util.RandomClass.Next(1))); + if (position.X > 255) + position.X = 255; + if (position.X < 0) + position.X = 0; + position.Y = s_tree.AbsolutePosition.Y + (1 * (-1 * Util.RandomClass.Next(1))); + if (position.Y > 255) + position.Y = 255; + if (position.Y < 0) + position.Y = 0; + + double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); + double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); + + position.X += (float) randX; + position.Y += (float) randY; + + UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (uuid == UUID.Zero) + uuid = m_scene.RegionInfo.MasterAvatarAssignedUUID; + + CreateTree(uuid, position); + } + + private void CreateTree(UUID uuid, Vector3 position) + { + position.Z = (float) m_scene.Heightmap[(int) position.X, (int) position.Y]; + + IVegetationModule module = m_scene.RequestModuleInterface(); + + if (null == module) + return; + + SceneObjectGroup tree + = module.AddTree( + uuid, UUID.Zero, new Vector3(0.1f, 0.1f, 0.1f), Quaternion.Identity, position, Tree.Cypress1, false); + + m_trees.Add(tree.UUID); + tree.SendGroupFullUpdate(); + } + + private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e) + { + growTrees(); + seedTrees(); + killTrees(); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs index 7eb00a7..cc78b51 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs @@ -29,8 +29,8 @@ using System; using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules.Avatar.Currency.SampleMoney; +using OpenSim.Region.CoreModules; using OpenSim.Region; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs index f1f5f4b..dc7716e 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs @@ -31,7 +31,7 @@ using System.Reflection; using log4net; using Nini.Config; using OpenSim.Framework; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules.Framework.EventQueue; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Interfaces; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2429e96..d1006e3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -37,11 +37,11 @@ using OpenMetaverse.Packets; using OpenSim; using OpenSim.Framework; using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; -using OpenSim.Region.Environment.Modules.World.Land; -using OpenSim.Region.Environment.Modules.World.Terrain; +using OpenSim.Region.CoreModules.Avatar.Currency.SampleMoney; +using OpenSim.Region.CoreModules.World.Land; +using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Physics.Manager; using OpenSim.Region.ScriptEngine.Shared; @@ -4168,7 +4168,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector SunDoubleVector3; Vector3 SunFloatVector3; - // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule + // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule // have to convert from Vector3 (float) to LSL_Vector (double) SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector; SunDoubleVector3.x = (double)SunFloatVector3.X; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs index 4c7dc8d..0654c07 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/HttpRequest.cs @@ -27,7 +27,7 @@ using System; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.Scripting.HttpRequest; +using OpenSim.Region.CoreModules.Scripting.HttpRequest; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared.Api; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs index eba52bf..5c95c66 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Listener.cs @@ -28,7 +28,7 @@ using System; using OpenMetaverse; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.Scripting.WorldComm; +using OpenSim.Region.CoreModules.Scripting.WorldComm; using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/XmlRequest.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/XmlRequest.cs index bf1a923..893977b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/XmlRequest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/XmlRequest.cs @@ -27,7 +27,7 @@ using System; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Environment.Modules.Scripting.XMLRPC; +using OpenSim.Region.CoreModules.Scripting.XMLRPC; using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp index 3cd6b76..feff86a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp @@ -33,7 +33,7 @@ - + diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 777cb12..4236c2b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -33,7 +33,7 @@ using System.Collections.Generic; using System.Runtime.Serialization; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules; using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.ScriptEngine.Shared diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 6b04248..a9a2dbf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -41,7 +41,7 @@ using log4net; using Nini.Config; using Amib.Threading; using OpenSim.Framework; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.ScriptEngine.Shared; diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs index 7e8d690..ef3ba9a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs @@ -39,7 +39,7 @@ using log4net; using Nini.Config; using Amib.Threading; using OpenSim.Framework; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.ScriptEngine.Shared; diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 09f751f..2632948 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -30,7 +30,7 @@ using System.Collections; using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; +using OpenSim.Region.CoreModules.Avatar.Currency.SampleMoney; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.ScriptEngine.Shared; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 2cb18ea..a5570b3 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -41,7 +41,7 @@ using log4net; using Nini.Config; using Amib.Threading; using OpenSim.Framework; -using OpenSim.Region.Environment; +using OpenSim.Region.CoreModules.Framework.EventQueue; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.ScriptEngine.Shared; diff --git a/TESTING.txt b/TESTING.txt index e818085..6eec2ef 100644 --- a/TESTING.txt +++ b/TESTING.txt @@ -60,7 +60,7 @@ have tests in them: OpenSim.Region.ScriptEngine.Common.Tests.dll OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests.dll OpenSim.Region.ScriptEngine.Shared.Tests.dll -OpenSim.Framework.Tests.dll OpenSim.Region.Environment.dll +OpenSim.Framework.Tests.dll OpenSim.Region.CoreModules.dll OpenSim.Region.Physics.OdePlugin.dll[2] The console command used to run the tests is `nunit-console` (or diff --git a/prebuild.xml b/prebuild.xml index 0cdb59e..5b5e271 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -888,7 +888,7 @@ - + ../../../bin/ @@ -930,10 +930,83 @@ + + + + + ../../../../../../bin/Terrain/ + + + + + ../../../../../../bin/Terrain/ + + + + ../../../../../../bin/ + + + + + + + + + + + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -994,6 +1067,7 @@ + @@ -1069,83 +1143,6 @@ - - - - ../../../../bin/ - - - - - ../../../../bin/ - - - - ../../../../bin/ - - - - - - - - - - - - - - - - - ../../../../../../bin/Terrain/ - - - - - ../../../../../../bin/Terrain/ - - - - ../../../../../../bin/ - - - - - - - - - - - - - ../../../../bin/ - - - - - ../../../../bin/ - - - - ../../../../bin/ - - - - - - - - - - - - - - - - @@ -1173,7 +1170,7 @@ - + @@ -1209,7 +1206,6 @@ - @@ -1246,7 +1242,7 @@ - + @@ -1283,7 +1279,7 @@ - + @@ -1318,7 +1314,7 @@ - + @@ -1357,7 +1353,7 @@ - + @@ -1396,7 +1392,7 @@ - + @@ -1623,7 +1619,7 @@ - + @@ -1660,7 +1656,7 @@ - + @@ -1694,7 +1690,7 @@ - + @@ -1730,7 +1726,7 @@ - + @@ -1764,7 +1760,7 @@ - + @@ -1800,7 +1796,7 @@ - + @@ -1840,7 +1836,7 @@ - + @@ -1880,7 +1876,7 @@ - + @@ -1940,7 +1936,7 @@ - + @@ -1978,7 +1974,7 @@ - + @@ -2019,7 +2015,7 @@ - + @@ -2058,7 +2054,7 @@ - + @@ -2098,7 +2094,7 @@ - + @@ -2139,7 +2135,7 @@ - + @@ -2180,7 +2176,7 @@ - + @@ -2220,7 +2216,7 @@ - + @@ -2266,7 +2262,7 @@ - + @@ -2374,7 +2370,6 @@ - @@ -2404,7 +2399,7 @@ - + @@ -2636,7 +2631,6 @@ - @@ -2665,7 +2659,7 @@ - + ../../../bin/ @@ -2692,7 +2686,7 @@ - + @@ -2717,8 +2711,8 @@ --> - - + + @@ -2749,7 +2743,7 @@ - + -- cgit v1.1