From f5c312bc3c2567449c7268a54a08a54119f58d53 Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Wed, 30 Apr 2008 21:16:36 +0000 Subject: [PATCH] * Refactored Environment/Modules directory - modules now reside in their own directory with any associated module-specific classes. * Each module directory is currently inside one of the following category folders: Agent (Anything relating to do with Client<->Server communications.), Avatar (Anything to do with the avatar or presence inworld), Framework (Classes modules can use), Grid (Grid traffic, new OGS2 grid comms), Scripting (Scripting functions, etc), World (The enrivonment/scene, IE Sun/Tree modules.) * This should be moved into a seperate project file. --- .../AssetDownload}/AssetDownloadModule.cs | 666 ++-- .../AgentAssetsTransactions.cs | 815 +++-- .../AssetTransactionModule.cs} | 572 ++-- .../TextureDownload}/TextureDownloadModule.cs | 433 ++- .../TextureDownload}/TextureNotFoundSender.cs | 186 +- .../UserTextureDownloadService.cs | 502 +-- .../TextureSender}/TextureSender.cs | 440 +-- .../Modules/{ => Agent/Xfer}/XferModule.cs | 450 +-- .../Modules/AppearanceTableMapper.cs | 244 -- .../AvatarFactory}/AvatarFactoryModule.cs | 676 ++-- .../Modules/{ => Avatar/Chat}/ChatModule.cs | 1662 ++++----- .../SampleMoney/SampleMoneyModule.cs} | 2981 +++++++++-------- .../{ => Avatar/Friends}/FriendsModule.cs | 1008 +++--- .../{ => Avatar/Groups}/GroupsModule.cs | 556 +-- .../InstantMessage}/InstantMessageModule.cs | 316 +- .../{ => Avatar/Inventory}/InventoryModule.cs | 432 +-- .../Profiles}/AvatarProfilesModule.cs | 258 +- .../AsterixVoice}/AsteriskVoiceModule.cs | 570 ++-- .../Voice/SIPVoice/SIPVoiceModule.cs} | 394 +-- .../Modules/CommanderTestModule.cs | 89 - .../Interregion/IInterregionModule.cs | 15 - .../Interregion/InterregionModule.cs | 174 - .../Interregion/RemotingObject.cs | 50 - .../Region/Environment/Modules/EmailModule.cs | 33 - .../ExportSerialisationModule.cs | 168 - .../ExportSerialiser/IFileSerialiser.cs | 36 - .../ExportSerialiser/IRegionSerialiser.cs | 37 - .../ExportSerialiser/SerialiseObjects.cs | 123 - .../ExportSerialiser/SerialiseTerrain.cs | 53 - .../Modules/LandManagement/LandChannel.cs | 1008 ------ .../LandManagement/LandManagementModule.cs | 85 - .../Modules/LandManagement/LandObject.cs | 947 ------ .../Modules/ModuleFramework/Commander.cs | 308 -- .../DynamicTexture}/DynamicTextureModule.cs | 554 +-- .../HttpRequest}/ScriptsHttpRequests.cs | 720 ++-- .../LoadImageURL}/LoadImageURLModule.cs | 359 +- .../VectorRender}/VectorRenderModule.cs | 722 ++-- .../WorldComm}/WorldCommModule.cs | 1162 ++++--- .../{ => Scripting/XMLRPC}/XMLRPCModule.cs | 1352 ++++---- .../Region/Environment/Modules/SunModule.cs | 195 -- .../Environment/Modules/TeleportModule.cs | 33 - .../Modules/Terrain/Effects/CookieCutter.cs | 124 - .../Effects/DefaultTerrainGenerator.cs | 55 - .../Modules/Terrain/FileLoaders/BMP.cs | 62 - .../Modules/Terrain/FileLoaders/GIF.cs | 47 - .../FileLoaders/GenericSystemDrawing.cs | 172 - .../Modules/Terrain/FileLoaders/JPEG.cs | 94 - .../Modules/Terrain/FileLoaders/LLRAW.cs | 148 - .../Modules/Terrain/FileLoaders/PNG.cs | 47 - .../Modules/Terrain/FileLoaders/RAW32.cs | 153 - .../Modules/Terrain/FileLoaders/TIFF.cs | 47 - .../Modules/Terrain/FileLoaders/Terragen.cs | 127 - .../Terrain/FloodBrushes/FlattenArea.cs | 71 - .../Modules/Terrain/FloodBrushes/LowerArea.cs | 54 - .../Modules/Terrain/FloodBrushes/NoiseArea.cs | 56 - .../Modules/Terrain/FloodBrushes/RaiseArea.cs | 53 - .../Terrain/FloodBrushes/RevertArea.cs | 60 - .../Terrain/FloodBrushes/SmoothArea.cs | 114 - .../Modules/Terrain/ITerrainEffect.cs | 36 - .../Modules/Terrain/ITerrainFloodEffect.cs | 37 - .../Modules/Terrain/ITerrainLoader.cs | 39 - .../Modules/Terrain/ITerrainModule.cs | 8 - .../Terrain/ITerrainPaintableEffect.cs | 36 - .../Modules/Terrain/MapImageModule.cs | 168 - .../Terrain/PaintBrushes/ErodeSphere.cs | 312 -- .../Terrain/PaintBrushes/FlattenSphere.cs | 127 - .../Terrain/PaintBrushes/LowerSphere.cs | 67 - .../Terrain/PaintBrushes/NoiseSphere.cs | 70 - .../Terrain/PaintBrushes/OlsenSphere.cs | 225 -- .../Terrain/PaintBrushes/RaiseSphere.cs | 67 - .../Terrain/PaintBrushes/RevertSphere.cs | 82 - .../Terrain/PaintBrushes/SmoothSphere.cs | 93 - .../Terrain/PaintBrushes/WeatherSphere.cs | 207 -- .../Modules/Terrain/TerrainChannel.cs | 157 - .../Modules/Terrain/TerrainException.cs | 46 - .../Modules/Terrain/TerrainModule.cs | 734 ---- .../Modules/Terrain/TerrainUtil.cs | 133 - .../Modules/TreePopulatorModule.cs | 248 -- 78 files changed, 8880 insertions(+), 16880 deletions(-) rename OpenSim/Region/Environment/Modules/{ => Agent/AssetDownload}/AssetDownloadModule.cs (94%) rename OpenSim/Region/Environment/Modules/{ => Agent/AssetTransaction}/AgentAssetsTransactions.cs (96%) rename OpenSim/Region/Environment/Modules/{AgentAssetTransactionModule.cs => Agent/AssetTransaction/AssetTransactionModule.cs} (89%) rename OpenSim/Region/Environment/Modules/{ => Agent/TextureDownload}/TextureDownloadModule.cs (96%) rename OpenSim/Region/Environment/Modules/{ => Agent/TextureDownload}/TextureNotFoundSender.cs (95%) rename OpenSim/Region/Environment/Modules/{ => Agent/TextureDownload}/UserTextureDownloadService.cs (90%) rename OpenSim/Region/Environment/Modules/{ => Agent/TextureSender}/TextureSender.cs (96%) rename OpenSim/Region/Environment/Modules/{ => Agent/Xfer}/XferModule.cs (96%) delete mode 100644 OpenSim/Region/Environment/Modules/AppearanceTableMapper.cs rename OpenSim/Region/Environment/Modules/{ => Avatar/AvatarFactory}/AvatarFactoryModule.cs (97%) rename OpenSim/Region/Environment/Modules/{ => Avatar/Chat}/ChatModule.cs (92%) rename OpenSim/Region/Environment/Modules/{BetaGridLikeMoneyModule.cs => Avatar/Currency/SampleMoney/SampleMoneyModule.cs} (93%) rename OpenSim/Region/Environment/Modules/{ => Avatar/Friends}/FriendsModule.cs (94%) rename OpenSim/Region/Environment/Modules/{ => Avatar/Groups}/GroupsModule.cs (93%) rename OpenSim/Region/Environment/Modules/{ => Avatar/InstantMessage}/InstantMessageModule.cs (89%) rename OpenSim/Region/Environment/Modules/{ => Avatar/Inventory}/InventoryModule.cs (80%) rename OpenSim/Region/Environment/Modules/{ => Avatar/Profiles}/AvatarProfilesModule.cs (90%) rename OpenSim/Region/Environment/Modules/{ => Avatar/Voice/AsterixVoice}/AsteriskVoiceModule.cs (93%) rename OpenSim/Region/Environment/Modules/{VoiceModule.cs => Avatar/Voice/SIPVoice/SIPVoiceModule.cs} (89%) delete mode 100644 OpenSim/Region/Environment/Modules/CommanderTestModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Communications/Interregion/IInterregionModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Communications/Interregion/InterregionModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Communications/Interregion/RemotingObject.cs delete mode 100644 OpenSim/Region/Environment/Modules/EmailModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/ExportSerialiser/ExportSerialisationModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/ExportSerialiser/IFileSerialiser.cs delete mode 100644 OpenSim/Region/Environment/Modules/ExportSerialiser/IRegionSerialiser.cs delete mode 100644 OpenSim/Region/Environment/Modules/ExportSerialiser/SerialiseObjects.cs delete mode 100644 OpenSim/Region/Environment/Modules/ExportSerialiser/SerialiseTerrain.cs delete mode 100644 OpenSim/Region/Environment/Modules/LandManagement/LandChannel.cs delete mode 100644 OpenSim/Region/Environment/Modules/LandManagement/LandManagementModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs delete mode 100644 OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs rename OpenSim/Region/Environment/Modules/{ => Scripting/DynamicTexture}/DynamicTextureModule.cs (90%) rename OpenSim/Region/Environment/Modules/{ => Scripting/HttpRequest}/ScriptsHttpRequests.cs (95%) rename OpenSim/Region/Environment/Modules/{ => Scripting/LoadImageURL}/LoadImageURLModule.cs (96%) rename OpenSim/Region/Environment/Modules/{ => Scripting/VectorRender}/VectorRenderModule.cs (96%) rename OpenSim/Region/Environment/Modules/{ => Scripting/WorldComm}/WorldCommModule.cs (91%) rename OpenSim/Region/Environment/Modules/{ => Scripting/XMLRPC}/XMLRPCModule.cs (96%) delete mode 100644 OpenSim/Region/Environment/Modules/SunModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/TeleportModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/Effects/CookieCutter.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/Effects/DefaultTerrainGenerator.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/BMP.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GIF.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GenericSystemDrawing.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/PNG.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/TIFF.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/FlattenArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/LowerArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/NoiseArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/RaiseArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/RevertArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/SmoothArea.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/ITerrainEffect.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/ITerrainFloodEffect.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/ITerrainLoader.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/ITerrainModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/ITerrainPaintableEffect.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/MapImageModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/FlattenSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/LowerSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/NoiseSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/OlsenSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RaiseSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RevertSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/SmoothSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/WeatherSphere.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/TerrainChannel.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/TerrainException.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Terrain/TerrainUtil.cs delete mode 100644 OpenSim/Region/Environment/Modules/TreePopulatorModule.cs diff --git a/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs b/OpenSim/Region/Environment/Modules/Agent/AssetDownload/AssetDownloadModule.cs similarity index 94% rename from OpenSim/Region/Environment/Modules/AssetDownloadModule.cs rename to OpenSim/Region/Environment/Modules/Agent/AssetDownload/AssetDownloadModule.cs index 97db31ed4d..47c1479672 100644 --- a/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/Agent/AssetDownload/AssetDownloadModule.cs @@ -1,333 +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 System.Collections.Generic; -using libsecondlife; -using libsecondlife.Packets; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class AssetDownloadModule : IRegionModule - { - private Scene m_scene; - private Dictionary RegisteredScenes = new Dictionary(); - /// - /// Assets requests (for each user) which are waiting for asset server data. This includes texture requests - /// - private Dictionary> RequestedAssets; - - /// - /// Asset requests with data which are ready to be sent back to requesters. This includes textures. - /// - private List AssetRequests; - - public AssetDownloadModule() - { - RequestedAssets = new Dictionary>(); - AssetRequests = new List(); - } - - public void Initialise(Scene scene, IConfigSource config) - { - if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) - { - RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); - // scene.EventManager.OnNewClient += NewClient; - } - - if (m_scene == null) - { - m_scene = scene; - // m_thread = new Thread(new ThreadStart(RunAssetQueue)); - // m_thread.Name = "AssetDownloadQueueThread"; - // m_thread.IsBackground = true; - // m_thread.Start(); - // OpenSim.Framework.ThreadTracker.Add(m_thread); - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "AssetDownloadModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public void NewClient(IClientAPI client) - { - // client.OnRequestAsset += AddAssetRequest; - } - - /// - /// Make an asset request the result of which will be packeted up and sent directly back to the client. - /// - /// - /// - public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) - { - LLUUID requestID = null; - byte source = 2; - if (transferRequest.TransferInfo.SourceType == 2) - { - //direct asset request - requestID = new LLUUID(transferRequest.TransferInfo.Params, 0); - } - else if (transferRequest.TransferInfo.SourceType == 3) - { - //inventory asset request - requestID = new LLUUID(transferRequest.TransferInfo.Params, 80); - source = 3; - //Console.WriteLine("asset request " + requestID); - } - - //not found asset - // so request from asset server - Dictionary userRequests = null; - if (RequestedAssets.TryGetValue(userInfo.AgentId, out userRequests)) - { - if (!userRequests.ContainsKey(requestID)) - { - AssetRequest request = new AssetRequest(); - request.RequestUser = userInfo; - request.RequestAssetID = requestID; - request.TransferRequestID = transferRequest.TransferInfo.TransferID; - request.AssetRequestSource = source; - request.Params = transferRequest.TransferInfo.Params; - userRequests[requestID] = request; - m_scene.AssetCache.GetAsset(requestID, AssetCallback, false); - } - } - else - { - userRequests = new Dictionary(); - AssetRequest request = new AssetRequest(); - request.RequestUser = userInfo; - request.RequestAssetID = requestID; - request.TransferRequestID = transferRequest.TransferInfo.TransferID; - request.AssetRequestSource = source; - request.Params = transferRequest.TransferInfo.Params; - userRequests.Add(requestID, request); - RequestedAssets[userInfo.AgentId] = userRequests; - m_scene.AssetCache.GetAsset(requestID, AssetCallback, false); - } - } - - public void AssetCallback(LLUUID assetID, AssetBase asset) - { - if (asset != null) - { - foreach (Dictionary userRequests in RequestedAssets.Values) - { - if (userRequests.ContainsKey(assetID)) - { - AssetRequest req = userRequests[assetID]; - if (req != null) - { - req.AssetInf = asset; - req.NumPackets = CalculateNumPackets(asset.Data); - - userRequests.Remove(assetID); - AssetRequests.Add(req); - } - } - } - } - } - -// TODO: unused -// private void RunAssetQueue() -// { -// while (true) -// { -// try -// { -// ProcessAssetQueue(); -// Thread.Sleep(500); -// } -// catch (Exception) -// { -// // m_log.Error("[ASSET CACHE]: " + e.ToString()); -// } -// } -// } - -// TODO: unused -// /// -// /// Process the asset queue which sends packets directly back to the client. -// /// -// private void ProcessAssetQueue() -// { -// //should move the asset downloading to a module, like has been done with texture downloading -// if (AssetRequests.Count == 0) -// { -// //no requests waiting -// return; -// } -// // if less than 5, do all of them -// int num = Math.Min(5, AssetRequests.Count); - -// AssetRequest req; -// for (int i = 0; i < num; i++) -// { -// req = (AssetRequest)AssetRequests[i]; -// //Console.WriteLine("sending asset " + req.RequestAssetID); -// TransferInfoPacket Transfer = new TransferInfoPacket(); -// Transfer.TransferInfo.ChannelType = 2; -// Transfer.TransferInfo.Status = 0; -// Transfer.TransferInfo.TargetType = 0; -// if (req.AssetRequestSource == 2) -// { -// Transfer.TransferInfo.Params = new byte[20]; -// Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); -// int assType = (int)req.AssetInf.Type; -// Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); -// } -// else if (req.AssetRequestSource == 3) -// { -// Transfer.TransferInfo.Params = req.Params; -// // Transfer.TransferInfo.Params = new byte[100]; -// //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); -// //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); -// } -// Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length; -// Transfer.TransferInfo.TransferID = req.TransferRequestID; -// req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset); - -// if (req.NumPackets == 1) -// { -// TransferPacketPacket TransferPacket = new TransferPacketPacket(); -// TransferPacket.TransferData.Packet = 0; -// TransferPacket.TransferData.ChannelType = 2; -// TransferPacket.TransferData.TransferID = req.TransferRequestID; -// TransferPacket.TransferData.Data = req.AssetInf.Data; -// TransferPacket.TransferData.Status = 1; -// req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); -// } -// else -// { -// int processedLength = 0; -// // libsecondlife hardcodes 1500 as the maximum data chunk size -// int maxChunkSize = 1250; -// int packetNumber = 0; - -// while (processedLength < req.AssetInf.Data.Length) -// { -// TransferPacketPacket TransferPacket = new TransferPacketPacket(); -// TransferPacket.TransferData.Packet = packetNumber; -// TransferPacket.TransferData.ChannelType = 2; -// TransferPacket.TransferData.TransferID = req.TransferRequestID; - -// int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); -// byte[] chunk = new byte[chunkSize]; -// Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); - -// TransferPacket.TransferData.Data = chunk; - -// // 0 indicates more packets to come, 1 indicates last packet -// if (req.AssetInf.Data.Length - processedLength > maxChunkSize) -// { -// TransferPacket.TransferData.Status = 0; -// } -// else -// { -// TransferPacket.TransferData.Status = 1; -// } - -// req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); - -// processedLength += chunkSize; -// packetNumber++; -// } -// } -// } - -// //remove requests that have been completed -// for (int i = 0; i < num; i++) -// { -// AssetRequests.RemoveAt(0); -// } -// } - - /// - /// Calculate the number of packets required to send the asset to the client. - /// - /// - /// - private int CalculateNumPackets(byte[] data) - { - const uint m_maxPacketSize = 600; - int numPackets = 1; - - if (data.LongLength > m_maxPacketSize) - { - // over max number of bytes so split up file - long restData = data.LongLength - m_maxPacketSize; - int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize); - numPackets += restPackets; - } - - return numPackets; - } - - public class AssetRequest - { - public IClientAPI RequestUser; - public LLUUID RequestAssetID; - public AssetBase AssetInf; - public AssetBase ImageInfo; - public LLUUID TransferRequestID; - public long DataPointer = 0; - public int NumPackets = 0; - public int PacketCounter = 0; - public bool IsTextureRequest; - public byte AssetRequestSource = 2; - public byte[] Params = null; - //public bool AssetInCache; - //public int TimeRequested; - public int DiscardLevel = -1; - - public AssetRequest() - { - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using libsecondlife.Packets; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Agent.AssetDownload +{ + public class AssetDownloadModule : IRegionModule + { + private Scene m_scene; + private Dictionary RegisteredScenes = new Dictionary(); + /// + /// Assets requests (for each user) which are waiting for asset server data. This includes texture requests + /// + private Dictionary> RequestedAssets; + + /// + /// Asset requests with data which are ready to be sent back to requesters. This includes textures. + /// + private List AssetRequests; + + public AssetDownloadModule() + { + RequestedAssets = new Dictionary>(); + AssetRequests = new List(); + } + + public void Initialise(Scene scene, IConfigSource config) + { + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) + { + RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); + // scene.EventManager.OnNewClient += NewClient; + } + + if (m_scene == null) + { + m_scene = scene; + // m_thread = new Thread(new ThreadStart(RunAssetQueue)); + // m_thread.Name = "AssetDownloadQueueThread"; + // m_thread.IsBackground = true; + // m_thread.Start(); + // OpenSim.Framework.ThreadTracker.Add(m_thread); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "AssetDownloadModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + // client.OnRequestAsset += AddAssetRequest; + } + + /// + /// Make an asset request the result of which will be packeted up and sent directly back to the client. + /// + /// + /// + public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) + { + LLUUID requestID = null; + byte source = 2; + if (transferRequest.TransferInfo.SourceType == 2) + { + //direct asset request + requestID = new LLUUID(transferRequest.TransferInfo.Params, 0); + } + else if (transferRequest.TransferInfo.SourceType == 3) + { + //inventory asset request + requestID = new LLUUID(transferRequest.TransferInfo.Params, 80); + source = 3; + //Console.WriteLine("asset request " + requestID); + } + + //not found asset + // so request from asset server + Dictionary userRequests = null; + if (RequestedAssets.TryGetValue(userInfo.AgentId, out userRequests)) + { + if (!userRequests.ContainsKey(requestID)) + { + AssetRequest request = new AssetRequest(); + request.RequestUser = userInfo; + request.RequestAssetID = requestID; + request.TransferRequestID = transferRequest.TransferInfo.TransferID; + request.AssetRequestSource = source; + request.Params = transferRequest.TransferInfo.Params; + userRequests[requestID] = request; + m_scene.AssetCache.GetAsset(requestID, AssetCallback, false); + } + } + else + { + userRequests = new Dictionary(); + AssetRequest request = new AssetRequest(); + request.RequestUser = userInfo; + request.RequestAssetID = requestID; + request.TransferRequestID = transferRequest.TransferInfo.TransferID; + request.AssetRequestSource = source; + request.Params = transferRequest.TransferInfo.Params; + userRequests.Add(requestID, request); + RequestedAssets[userInfo.AgentId] = userRequests; + m_scene.AssetCache.GetAsset(requestID, AssetCallback, false); + } + } + + public void AssetCallback(LLUUID assetID, AssetBase asset) + { + if (asset != null) + { + foreach (Dictionary userRequests in RequestedAssets.Values) + { + if (userRequests.ContainsKey(assetID)) + { + AssetRequest req = userRequests[assetID]; + if (req != null) + { + req.AssetInf = asset; + req.NumPackets = CalculateNumPackets(asset.Data); + + userRequests.Remove(assetID); + AssetRequests.Add(req); + } + } + } + } + } + +// TODO: unused +// private void RunAssetQueue() +// { +// while (true) +// { +// try +// { +// ProcessAssetQueue(); +// Thread.Sleep(500); +// } +// catch (Exception) +// { +// // m_log.Error("[ASSET CACHE]: " + e.ToString()); +// } +// } +// } + +// TODO: unused +// /// +// /// Process the asset queue which sends packets directly back to the client. +// /// +// private void ProcessAssetQueue() +// { +// //should move the asset downloading to a module, like has been done with texture downloading +// if (AssetRequests.Count == 0) +// { +// //no requests waiting +// return; +// } +// // if less than 5, do all of them +// int num = Math.Min(5, AssetRequests.Count); + +// AssetRequest req; +// for (int i = 0; i < num; i++) +// { +// req = (AssetRequest)AssetRequests[i]; +// //Console.WriteLine("sending asset " + req.RequestAssetID); +// TransferInfoPacket Transfer = new TransferInfoPacket(); +// Transfer.TransferInfo.ChannelType = 2; +// Transfer.TransferInfo.Status = 0; +// Transfer.TransferInfo.TargetType = 0; +// if (req.AssetRequestSource == 2) +// { +// Transfer.TransferInfo.Params = new byte[20]; +// Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); +// int assType = (int)req.AssetInf.Type; +// Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); +// } +// else if (req.AssetRequestSource == 3) +// { +// Transfer.TransferInfo.Params = req.Params; +// // Transfer.TransferInfo.Params = new byte[100]; +// //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); +// //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); +// } +// Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length; +// Transfer.TransferInfo.TransferID = req.TransferRequestID; +// req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset); + +// if (req.NumPackets == 1) +// { +// TransferPacketPacket TransferPacket = new TransferPacketPacket(); +// TransferPacket.TransferData.Packet = 0; +// TransferPacket.TransferData.ChannelType = 2; +// TransferPacket.TransferData.TransferID = req.TransferRequestID; +// TransferPacket.TransferData.Data = req.AssetInf.Data; +// TransferPacket.TransferData.Status = 1; +// req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); +// } +// else +// { +// int processedLength = 0; +// // libsecondlife hardcodes 1500 as the maximum data chunk size +// int maxChunkSize = 1250; +// int packetNumber = 0; + +// while (processedLength < req.AssetInf.Data.Length) +// { +// TransferPacketPacket TransferPacket = new TransferPacketPacket(); +// TransferPacket.TransferData.Packet = packetNumber; +// TransferPacket.TransferData.ChannelType = 2; +// TransferPacket.TransferData.TransferID = req.TransferRequestID; + +// int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); +// byte[] chunk = new byte[chunkSize]; +// Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); + +// TransferPacket.TransferData.Data = chunk; + +// // 0 indicates more packets to come, 1 indicates last packet +// if (req.AssetInf.Data.Length - processedLength > maxChunkSize) +// { +// TransferPacket.TransferData.Status = 0; +// } +// else +// { +// TransferPacket.TransferData.Status = 1; +// } + +// req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + +// processedLength += chunkSize; +// packetNumber++; +// } +// } +// } + +// //remove requests that have been completed +// for (int i = 0; i < num; i++) +// { +// AssetRequests.RemoveAt(0); +// } +// } + + /// + /// Calculate the number of packets required to send the asset to the client. + /// + /// + /// + private int CalculateNumPackets(byte[] data) + { + const uint m_maxPacketSize = 600; + int numPackets = 1; + + if (data.LongLength > m_maxPacketSize) + { + // over max number of bytes so split up file + long restData = data.LongLength - m_maxPacketSize; + int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize); + numPackets += restPackets; + } + + return numPackets; + } + + public class AssetRequest + { + public IClientAPI RequestUser; + public LLUUID RequestAssetID; + public AssetBase AssetInf; + public AssetBase ImageInfo; + public LLUUID TransferRequestID; + public long DataPointer = 0; + public int NumPackets = 0; + public int PacketCounter = 0; + public bool IsTextureRequest; + public byte AssetRequestSource = 2; + public byte[] Params = null; + //public bool AssetInCache; + //public int TimeRequested; + public int DiscardLevel = -1; + + public AssetRequest() + { + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/AgentAssetsTransactions.cs b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AgentAssetsTransactions.cs similarity index 96% rename from OpenSim/Region/Environment/Modules/AgentAssetsTransactions.cs rename to OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AgentAssetsTransactions.cs index 9fa173de84..74bb247000 100644 --- a/OpenSim/Region/Environment/Modules/AgentAssetsTransactions.cs +++ b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -1,408 +1,407 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using libsecondlife.Packets; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; - -namespace OpenSim.Region.Environment.Modules -{ - - /// - /// Manage asset transactions for a single agent. - /// - public class AgentAssetTransactions - { - //private static readonly log4net.ILog m_log - // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - // Fields - public LLUUID UserID; - public Dictionary XferUploaders = new Dictionary(); - public AgentAssetTransactionsManager Manager; - private bool m_dumpAssetsToFile; - - // Methods - public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile) - { - UserID = agentID; - Manager = manager; - m_dumpAssetsToFile = dumpAssetsToFile; - } - - public AssetXferUploader RequestXferUploader(LLUUID transactionID) - { - if (!XferUploaders.ContainsKey(transactionID)) - { - AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile); - - lock (XferUploaders) - { - XferUploaders.Add(transactionID, uploader); - } - - return uploader; - } - return null; - } - - public void HandleXfer(ulong xferID, uint packetID, byte[] data) - { - // AssetXferUploader uploaderFound = null; - - lock (XferUploaders) - { - foreach (AssetXferUploader uploader in XferUploaders.Values) - { - if (uploader.XferID == xferID) - { - uploader.HandleXferPacket(xferID, packetID, data); - break; - } - } - } - } - - public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, - uint callbackID, string description, string name, sbyte invType, - sbyte type, byte wearableType, uint nextOwnerMask) - { - if (XferUploaders.ContainsKey(transactionID)) - { - XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID, - callbackID, description, name, invType, type, - wearableType, nextOwnerMask); - } - } - - public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, - InventoryItemBase item) - { - if (XferUploaders.ContainsKey(transactionID)) - { - XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item); - } - } - - /// - /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed. - /// - /// - /// The asset if the upload has completed, null if it has not. - public AssetBase GetTransactionAsset(LLUUID transactionID) - { - if (XferUploaders.ContainsKey(transactionID)) - { - AssetXferUploader uploader = XferUploaders[transactionID]; - AssetBase asset = uploader.GetAssetData(); - - lock (XferUploaders) - { - XferUploaders.Remove(transactionID); - } - - return asset; - } - - return null; - } - - // Nested Types - public class AssetXferUploader - { - // Fields - public bool AddToInventory; - public AssetBase Asset; - public LLUUID InventFolder = LLUUID.Zero; - private IClientAPI ourClient; - public LLUUID TransactionID = LLUUID.Zero; - public bool UploadComplete; - public ulong XferID; - private string m_name = String.Empty; - private string m_description = String.Empty; - private sbyte type = 0; - private sbyte invType = 0; - private byte wearableType = 0; - private uint nextPerm = 0; - private bool m_finished = false; - private bool m_createItem = false; - private AgentAssetTransactions m_userTransactions; - private bool m_storeLocal; - private bool m_dumpAssetToFile; - - public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile) - { - m_userTransactions = transactions; - m_dumpAssetToFile = dumpAssetToFile; - } - - /// - /// Process transfer data received from the client. - /// - /// - /// - /// - /// True if the transfer is complete, false otherwise or if the xferID was not valid - public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) - { - if (XferID == xferID) - { - if (Asset.Data.Length > 1) - { - byte[] destinationArray = new byte[Asset.Data.Length + data.Length]; - Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length); - Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length); - Asset.Data = destinationArray; - } - else - { - byte[] buffer2 = new byte[data.Length - 4]; - Array.Copy(data, 4, buffer2, 0, data.Length - 4); - Asset.Data = buffer2; - } - ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); - newPack.XferID.ID = xferID; - newPack.XferID.Packet = packetID; - ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); - if ((packetID & 0x80000000) != 0) - { - SendCompleteMessage(); - return true; - } - } - - return false; - } - - /// - /// Initialise asset transfer from the client - /// - /// - /// - /// - /// True if the transfer is complete, false otherwise - public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, - bool storeLocal, bool tempFile) - { - ourClient = remoteClient; - Asset = new AssetBase(); - Asset.FullID = assetID; - Asset.InvType = type; - Asset.Type = type; - Asset.Data = data; - Asset.Name = "blank"; - Asset.Description = "empty"; - Asset.Local = storeLocal; - Asset.Temporary = tempFile; - - TransactionID = transaction; - m_storeLocal = storeLocal; - if (Asset.Data.Length > 2) - { - SendCompleteMessage(); - return true; - } - else - { - RequestStartXfer(); - } - - return false; - } - - protected void RequestStartXfer() - { - UploadComplete = false; - XferID = Util.GetNextXferID(); - RequestXferPacket newPack = new RequestXferPacket(); - newPack.XferID.ID = XferID; - newPack.XferID.VFileType = Asset.Type; - newPack.XferID.VFileID = Asset.FullID; - newPack.XferID.FilePath = 0; - newPack.XferID.Filename = new byte[0]; - ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); - } - - protected void SendCompleteMessage() - { - UploadComplete = true; - AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); - newPack.AssetBlock.Type = Asset.Type; - newPack.AssetBlock.Success = true; - newPack.AssetBlock.UUID = Asset.FullID; - ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); - m_finished = true; - if (m_createItem) - { - DoCreateItem(); - } - else if (m_storeLocal) - { - m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); - } - - // Console.WriteLine("upload complete "+ this.TransactionID); - - if (m_dumpAssetToFile) - { - DateTime now = DateTime.Now; - string filename = - String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day, - now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type); - SaveAssetToFile(filename, Asset.Data); - } - } - - ///Left this in and commented in case there are unforseen issues - //private void SaveAssetToFile(string filename, byte[] data) - //{ - // FileStream fs = File.Create(filename); - // BinaryWriter bw = new BinaryWriter(fs); - // bw.Write(data); - // bw.Close(); - // fs.Close(); - //} - private void SaveAssetToFile(string filename, byte[] data) - { - string assetPath = "UserAssets"; - if (!Directory.Exists(assetPath)) - { - Directory.CreateDirectory(assetPath); - } - FileStream fs = File.Create(Path.Combine(assetPath, filename)); - BinaryWriter bw = new BinaryWriter(fs); - bw.Write(data); - bw.Close(); - fs.Close(); - } - - public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, - uint callbackID, string description, string name, sbyte invType, - sbyte type, byte wearableType, uint nextOwnerMask) - { - if (TransactionID == transactionID) - { - InventFolder = folderID; - m_name = name; - m_description = description; - this.type = type; - this.invType = invType; - this.wearableType = wearableType; - nextPerm = nextOwnerMask; - Asset.Name = name; - Asset.Description = description; - Asset.Type = type; - Asset.InvType = invType; - m_createItem = true; - if (m_finished) - { - DoCreateItem(); - } - } - } - - public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, - InventoryItemBase item) - { - if (TransactionID == transactionID) - { - CachedUserInfo userInfo = - m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( - remoteClient.AgentId); - - if (userInfo != null) - { - LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId); - - AssetBase asset - = m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset( - assetID, (item.AssetType == (int) AssetType.Texture ? true : false)); - - if (asset == null) - { - asset = m_userTransactions.GetTransactionAsset(transactionID); - } - - if (asset != null && asset.FullID == assetID) - { - asset.Name = item.Name; - asset.Description = item.Description; - asset.InvType = (sbyte) item.InvType; - asset.Type = (sbyte) item.AssetType; - item.AssetID = asset.FullID; - - m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); - } - - userInfo.UpdateItem(remoteClient.AgentId, item); - } - } - } - - private void DoCreateItem() - { - //really need to fix this call, if lbsa71 saw this he would die. - m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); - CachedUserInfo userInfo = - m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId); - if (userInfo != null) - { - InventoryItemBase item = new InventoryItemBase(); - item.Owner = ourClient.AgentId; - item.Creator = ourClient.AgentId; - item.ID = LLUUID.Random(); - item.AssetID = Asset.FullID; - item.Description = m_description; - item.Name = m_name; - item.AssetType = type; - item.InvType = invType; - item.Folder = InventFolder; - item.BasePermissions = 2147483647; - item.CurrentPermissions = 2147483647; - item.NextPermissions = nextPerm; - item.Flags = (uint)wearableType; - - userInfo.AddItem(ourClient.AgentId, item); - ourClient.SendInventoryItemCreateUpdate(item); - } - } - - public AssetBase GetAssetData() - { - if (m_finished) - { - return Asset; - } - return null; - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction +{ + /// + /// Manage asset transactions for a single agent. + /// + public class AgentAssetTransactions + { + //private static readonly log4net.ILog m_log + // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + public LLUUID UserID; + public Dictionary XferUploaders = new Dictionary(); + public AgentAssetTransactionsManager Manager; + private bool m_dumpAssetsToFile; + + // Methods + public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile) + { + UserID = agentID; + Manager = manager; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + public AssetXferUploader RequestXferUploader(LLUUID transactionID) + { + if (!XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile); + + lock (XferUploaders) + { + XferUploaders.Add(transactionID, uploader); + } + + return uploader; + } + return null; + } + + public void HandleXfer(ulong xferID, uint packetID, byte[] data) + { + // AssetXferUploader uploaderFound = null; + + lock (XferUploaders) + { + foreach (AssetXferUploader uploader in XferUploaders.Values) + { + if (uploader.XferID == xferID) + { + uploader.HandleXferPacket(xferID, packetID, data); + break; + } + } + } + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (XferUploaders.ContainsKey(transactionID)) + { + XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID, + callbackID, description, name, invType, type, + wearableType, nextOwnerMask); + } + } + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + if (XferUploaders.ContainsKey(transactionID)) + { + XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + } + + /// + /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed. + /// + /// + /// The asset if the upload has completed, null if it has not. + public AssetBase GetTransactionAsset(LLUUID transactionID) + { + if (XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = XferUploaders[transactionID]; + AssetBase asset = uploader.GetAssetData(); + + lock (XferUploaders) + { + XferUploaders.Remove(transactionID); + } + + return asset; + } + + return null; + } + + // Nested Types + public class AssetXferUploader + { + // Fields + public bool AddToInventory; + public AssetBase Asset; + public LLUUID InventFolder = LLUUID.Zero; + private IClientAPI ourClient; + public LLUUID TransactionID = LLUUID.Zero; + public bool UploadComplete; + public ulong XferID; + private string m_name = String.Empty; + private string m_description = String.Empty; + private sbyte type = 0; + private sbyte invType = 0; + private byte wearableType = 0; + private uint nextPerm = 0; + private bool m_finished = false; + private bool m_createItem = false; + private AgentAssetTransactions m_userTransactions; + private bool m_storeLocal; + private bool m_dumpAssetToFile; + + public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile) + { + m_userTransactions = transactions; + m_dumpAssetToFile = dumpAssetToFile; + } + + /// + /// Process transfer data received from the client. + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise or if the xferID was not valid + public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) + { + if (XferID == xferID) + { + if (Asset.Data.Length > 1) + { + byte[] destinationArray = new byte[Asset.Data.Length + data.Length]; + Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length); + Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length); + Asset.Data = destinationArray; + } + else + { + byte[] buffer2 = new byte[data.Length - 4]; + Array.Copy(data, 4, buffer2, 0, data.Length - 4); + Asset.Data = buffer2; + } + ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); + newPack.XferID.ID = xferID; + newPack.XferID.Packet = packetID; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + if ((packetID & 0x80000000) != 0) + { + SendCompleteMessage(); + return true; + } + } + + return false; + } + + /// + /// Initialise asset transfer from the client + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise + public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, + bool storeLocal, bool tempFile) + { + ourClient = remoteClient; + Asset = new AssetBase(); + Asset.FullID = assetID; + Asset.InvType = type; + Asset.Type = type; + Asset.Data = data; + Asset.Name = "blank"; + Asset.Description = "empty"; + Asset.Local = storeLocal; + Asset.Temporary = tempFile; + + TransactionID = transaction; + m_storeLocal = storeLocal; + if (Asset.Data.Length > 2) + { + SendCompleteMessage(); + return true; + } + else + { + RequestStartXfer(); + } + + return false; + } + + protected void RequestStartXfer() + { + UploadComplete = false; + XferID = Util.GetNextXferID(); + RequestXferPacket newPack = new RequestXferPacket(); + newPack.XferID.ID = XferID; + newPack.XferID.VFileType = Asset.Type; + newPack.XferID.VFileID = Asset.FullID; + newPack.XferID.FilePath = 0; + newPack.XferID.Filename = new byte[0]; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + } + + protected void SendCompleteMessage() + { + UploadComplete = true; + AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); + newPack.AssetBlock.Type = Asset.Type; + newPack.AssetBlock.Success = true; + newPack.AssetBlock.UUID = Asset.FullID; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + m_finished = true; + if (m_createItem) + { + DoCreateItem(); + } + else if (m_storeLocal) + { + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); + } + + // Console.WriteLine("upload complete "+ this.TransactionID); + + if (m_dumpAssetToFile) + { + DateTime now = DateTime.Now; + string filename = + String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day, + now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type); + SaveAssetToFile(filename, Asset.Data); + } + } + + ///Left this in and commented in case there are unforseen issues + //private void SaveAssetToFile(string filename, byte[] data) + //{ + // FileStream fs = File.Create(filename); + // BinaryWriter bw = new BinaryWriter(fs); + // bw.Write(data); + // bw.Close(); + // fs.Close(); + //} + private void SaveAssetToFile(string filename, byte[] data) + { + string assetPath = "UserAssets"; + if (!Directory.Exists(assetPath)) + { + Directory.CreateDirectory(assetPath); + } + FileStream fs = File.Create(Path.Combine(assetPath, filename)); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (TransactionID == transactionID) + { + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + this.wearableType = wearableType; + nextPerm = nextOwnerMask; + Asset.Name = name; + Asset.Description = description; + Asset.Type = type; + Asset.InvType = invType; + m_createItem = true; + if (m_finished) + { + DoCreateItem(); + } + } + } + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + if (TransactionID == transactionID) + { + CachedUserInfo userInfo = + m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( + remoteClient.AgentId); + + if (userInfo != null) + { + LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId); + + AssetBase asset + = m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset( + assetID, (item.AssetType == (int) AssetType.Texture ? true : false)); + + if (asset == null) + { + asset = m_userTransactions.GetTransactionAsset(transactionID); + } + + if (asset != null && asset.FullID == assetID) + { + asset.Name = item.Name; + asset.Description = item.Description; + asset.InvType = (sbyte) item.InvType; + asset.Type = (sbyte) item.AssetType; + item.AssetID = asset.FullID; + + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); + } + + userInfo.UpdateItem(remoteClient.AgentId, item); + } + } + } + + private void DoCreateItem() + { + //really need to fix this call, if lbsa71 saw this he would die. + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); + CachedUserInfo userInfo = + m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId); + if (userInfo != null) + { + InventoryItemBase item = new InventoryItemBase(); + item.Owner = ourClient.AgentId; + item.Creator = ourClient.AgentId; + item.ID = LLUUID.Random(); + item.AssetID = Asset.FullID; + item.Description = m_description; + item.Name = m_name; + item.AssetType = type; + item.InvType = invType; + item.Folder = InventFolder; + item.BasePermissions = 2147483647; + item.CurrentPermissions = 2147483647; + item.NextPermissions = nextPerm; + item.Flags = (uint)wearableType; + + userInfo.AddItem(ourClient.AgentId, item); + ourClient.SendInventoryItemCreateUpdate(item); + } + } + + public AssetBase GetAssetData() + { + if (m_finished) + { + return Asset; + } + return null; + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/AgentAssetTransactionModule.cs b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetTransactionModule.cs similarity index 89% rename from OpenSim/Region/Environment/Modules/AgentAssetTransactionModule.cs rename to OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetTransactionModule.cs index cec71924f4..ef816254d1 100644 --- a/OpenSim/Region/Environment/Modules/AgentAssetTransactionModule.cs +++ b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -1,286 +1,286 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class AgentAssetTransactionModule : IRegionModule, IAgentAssetTransactions - { - private Dictionary RegisteredScenes = new Dictionary(); - private Scene m_scene = null; - private bool m_dumpAssetsToFile = false; - - private AgentAssetTransactionsManager m_transactionManager; - - public AgentAssetTransactionModule() - { - // System.Console.WriteLine("creating AgentAssetTransactionModule"); - } - - public void Initialise(Scene scene, IConfigSource config) - { - if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) - { - // System.Console.WriteLine("initialising AgentAssetTransactionModule"); - RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); - scene.RegisterModuleInterface(this); - - scene.EventManager.OnNewClient += NewClient; - } - - if (m_scene == null) - { - m_scene = scene; - if (config.Configs["StandAlone"] != null) - { - try - { - m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false); - m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile); - } - catch (Exception) - { - m_transactionManager = new AgentAssetTransactionsManager(m_scene, false); - } - } - else - { - m_transactionManager = new AgentAssetTransactionsManager(m_scene, false); - } - - } - } - - public void PostInitialise() - { - - } - - public void Close() - { - } - - public string Name - { - get { return "AgentTransactionModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public void NewClient(IClientAPI client) - { - client.OnAssetUploadRequest += m_transactionManager.HandleUDPUploadRequest; - client.OnXferReceive += m_transactionManager.HandleXfer; - } - - public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, - uint callbackID, string description, string name, sbyte invType, - sbyte type, byte wearableType, uint nextOwnerMask) - { - m_transactionManager.HandleItemCreationFromTransaction(remoteClient, transactionID, folderID, callbackID, description, name, invType, type, wearableType, nextOwnerMask); - } - - public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, - InventoryItemBase item) - { - m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); - } - - public void RemoveAgentAssetTransactions(LLUUID userID) - { - m_transactionManager.RemoveAgentAssetTransactions(userID); - } - } - - //should merge this classes and clean up - public class AgentAssetTransactionsManager - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // Fields - public Scene MyScene; - - /// - /// Each agent has its own singleton collection of transactions - /// - private Dictionary AgentTransactions = - new Dictionary(); - - /// - /// Should we dump uploaded assets to the filesystem? - /// - private bool m_dumpAssetsToFile; - - public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile) - { - MyScene = scene; - m_dumpAssetsToFile = dumpAssetsToFile; - } - - /// - /// Get the collection of asset transactions for the given user. If one does not already exist, it - /// is created. - /// - /// - /// - private AgentAssetTransactions GetUserTransactions(LLUUID userID) - { - lock (AgentTransactions) - { - if (!AgentTransactions.ContainsKey(userID)) - { - AgentAssetTransactions transactions - = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile); - AgentTransactions.Add(userID, transactions); - } - - return AgentTransactions[userID]; - } - } - - /// - /// Remove the given agent asset transactions. This should be called when a client is departing - /// from a scene (and hence won't be making any more transactions here). - /// - /// - public void RemoveAgentAssetTransactions(LLUUID userID) - { - // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); - - lock (AgentTransactions) - { - AgentTransactions.Remove(userID); - } - } - - /// - /// Create an inventory item from data that has been received through a transaction. - /// - /// This is called when new clothing or body parts are created. It may also be called in other - /// situations. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, - uint callbackID, string description, string name, sbyte invType, - sbyte type, byte wearableType, uint nextOwnerMask) - { - m_log.DebugFormat( - "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); - - AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - - transactions.RequestCreateInventoryItem( - remoteClient, transactionID, folderID, callbackID, description, - name, invType, type, wearableType, nextOwnerMask); - } - - /// - /// Update an inventory item with data that has been received through a transaction. - /// - /// This is called when clothing or body parts are updated (for instance, with new textures or - /// colours). It may also be called in other situations. - /// - /// - /// - /// - public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, - InventoryItemBase item) - { - m_log.DebugFormat( - "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", - item.Name); - - AgentAssetTransactions transactions - = GetUserTransactions(remoteClient.AgentId); - - transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); - } - - /// - /// Request that a client (agent) begin an asset transfer. - /// - /// - /// - /// - /// - /// - /// - public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, - byte[] data, bool storeLocal, bool tempFile) - { - // Console.WriteLine("asset upload of " + assetID); - AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - - AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction); - if (uploader != null) - { - - if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile)) - { - - } - } - } - - /// - /// Handle asset transfer data packets received in response to the asset upload request in - /// HandleUDPUploadRequest() - /// - /// - /// - /// - /// - public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) - { - AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - - transactions.HandleXfer(xferID, packetID, data); - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules.Agent.AssetTransaction; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction +{ + public class AssetTransactionModule : IRegionModule, IAgentAssetTransactions + { + private readonly Dictionary RegisteredScenes = new Dictionary(); + private Scene m_scene = null; + private bool m_dumpAssetsToFile = false; + + private AgentAssetTransactionsManager m_transactionManager; + + public AssetTransactionModule() + { + // System.Console.WriteLine("creating AgentAssetTransactionModule"); + } + + public void Initialise(Scene scene, IConfigSource config) + { + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) + { + // System.Console.WriteLine("initialising AgentAssetTransactionModule"); + RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); + scene.RegisterModuleInterface(this); + + scene.EventManager.OnNewClient += NewClient; + } + + if (m_scene == null) + { + m_scene = scene; + if (config.Configs["StandAlone"] != null) + { + try + { + m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false); + m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile); + } + catch (Exception) + { + m_transactionManager = new AgentAssetTransactionsManager(m_scene, false); + } + } + else + { + m_transactionManager = new AgentAssetTransactionsManager(m_scene, false); + } + + } + } + + public void PostInitialise() + { + + } + + public void Close() + { + } + + public string Name + { + get { return "AgentTransactionModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + client.OnAssetUploadRequest += m_transactionManager.HandleUDPUploadRequest; + client.OnXferReceive += m_transactionManager.HandleXfer; + } + + public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + m_transactionManager.HandleItemCreationFromTransaction(remoteClient, transactionID, folderID, callbackID, description, name, invType, type, wearableType, nextOwnerMask); + } + + public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); + } + + public void RemoveAgentAssetTransactions(LLUUID userID) + { + m_transactionManager.RemoveAgentAssetTransactions(userID); + } + } + + public class AgentAssetTransactionsManager + { + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + public Scene MyScene; + + /// + /// Each agent has its own singleton collection of transactions + /// + private Dictionary AgentTransactions = + new Dictionary(); + + /// + /// Should we dump uploaded assets to the filesystem? + /// + private bool m_dumpAssetsToFile; + + public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile) + { + MyScene = scene; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + /// + /// Get the collection of asset transactions for the given user. If one does not already exist, it + /// is created. + /// + /// + /// + private AgentAssetTransactions GetUserTransactions(LLUUID userID) + { + lock (AgentTransactions) + { + if (!AgentTransactions.ContainsKey(userID)) + { + AgentAssetTransactions transactions + = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile); + AgentTransactions.Add(userID, transactions); + } + + return AgentTransactions[userID]; + } + } + + /// + /// Remove the given agent asset transactions. This should be called when a client is departing + /// from a scene (and hence won't be making any more transactions here). + /// + /// + public void RemoveAgentAssetTransactions(LLUUID userID) + { + // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); + + lock (AgentTransactions) + { + AgentTransactions.Remove(userID); + } + } + + /// + /// Create an inventory item from data that has been received through a transaction. + /// + /// This is called when new clothing or body parts are created. It may also be called in other + /// situations. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + m_log.DebugFormat( + "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, type, wearableType, nextOwnerMask); + } + + /// + /// Update an inventory item with data that has been received through a transaction. + /// + /// This is called when clothing or body parts are updated (for instance, with new textures or + /// colours). It may also be called in other situations. + /// + /// + /// + /// + public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + m_log.DebugFormat( + "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", + item.Name); + + AgentAssetTransactions transactions + = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + + /// + /// Request that a client (agent) begin an asset transfer. + /// + /// + /// + /// + /// + /// + /// + public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, + byte[] data, bool storeLocal, bool tempFile) + { + // Console.WriteLine("asset upload of " + assetID); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction); + if (uploader != null) + { + + if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile)) + { + + } + } + } + + /// + /// Handle asset transfer data packets received in response to the asset upload request in + /// HandleUDPUploadRequest() + /// + /// + /// + /// + /// + public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.HandleXfer(xferID, packetID, data); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs similarity index 96% rename from OpenSim/Region/Environment/Modules/TextureDownloadModule.cs rename to OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs index bde0dc0c22..b8899d2e99 100644 --- a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs @@ -1,218 +1,215 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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.Threading; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - //this is a first attempt, to start breaking the mess thats called the assetcache up. - // basically this should be the texture sending (to clients) code moved out of assetcache - //and some small clean up - public class TextureDownloadModule : IRegionModule - { - //private static readonly log4net.ILog m_log - // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - private List m_scenes = new List(); - - /// - /// There is one queue for all textures waiting to be sent, regardless of the requesting user. - /// - private readonly BlockingQueue m_queueSenders - = new BlockingQueue(); - - /// - /// Each user has their own texture download service. - /// - private readonly Dictionary m_userTextureServices = - new Dictionary(); - - private Thread m_thread; - - public TextureDownloadModule() - { - } - - public void Initialise(Scene scene, IConfigSource config) - { - if (m_scene == null) - { - //Console.WriteLine("Creating Texture download module"); - m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); - m_thread.Name = "ProcessTextureSenderThread"; - m_thread.IsBackground = true; - m_thread.Start(); - ThreadTracker.Add(m_thread); - } - - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - m_scene = scene; - m_scene.EventManager.OnNewClient += NewClient; - m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence; - } - } - - /// - /// Cleanup the texture service related objects for the removed presence. - /// - /// - private void EventManager_OnRemovePresence(LLUUID agentId) - { - UserTextureDownloadService textureService; - - lock (m_userTextureServices) - { - if (m_userTextureServices.TryGetValue(agentId, out textureService)) - { - textureService.Close(); - - m_userTextureServices.Remove(agentId); - } - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "TextureDownloadModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void NewClient(IClientAPI client) - { - client.OnRequestTexture += TextureRequest; - } - - /// - /// Does this user have a registered texture download service? - /// - /// - /// - /// Always returns true, since a service is created if one does not already exist - private bool TryGetUserTextureService( - IClientAPI client, out UserTextureDownloadService textureService) - { - lock (m_userTextureServices) - { - if (m_userTextureServices.TryGetValue(client.AgentId, out textureService)) - { - return true; - } - - textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders); - m_userTextureServices.Add(client.AgentId, textureService); - - return true; - } - } - - /// - /// Start the process of requesting a given texture. - /// - /// - /// - public void TextureRequest(Object sender, TextureRequestArgs e) - { - IClientAPI client = (IClientAPI) sender; - UserTextureDownloadService textureService; - - if (TryGetUserTextureService(client, out textureService)) - { - textureService.HandleTextureRequest(e); - } - } - - /// - /// Entry point for the thread dedicated to processing the texture queue. - /// - public void ProcessTextureSenders() - { - ITextureSender sender = null; - - while (true) - { - sender = m_queueSenders.Dequeue(); - - if (sender.Cancel) - { - TextureSent(sender); - - sender.Cancel = false; - } - else - { - bool finished = sender.SendTexturePacket(); - if (finished) - { - TextureSent(sender); - } - else - { - m_queueSenders.Enqueue(sender); - } - } - - // Make sure that any sender we currently have can get garbage collected - sender = null; - - //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count()); - } - } - - /// - /// Called when the texture has finished sending. - /// - /// - private void TextureSent(ITextureSender sender) - { - sender.Sending = false; - //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID); - m_scene.AddPendingDownloads(-1); - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload +{ + public class TextureDownloadModule : IRegionModule + { + //private static readonly log4net.ILog m_log + // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private List m_scenes = new List(); + + /// + /// There is one queue for all textures waiting to be sent, regardless of the requesting user. + /// + private readonly BlockingQueue m_queueSenders + = new BlockingQueue(); + + /// + /// Each user has their own texture download service. + /// + private readonly Dictionary m_userTextureServices = + new Dictionary(); + + private Thread m_thread; + + public TextureDownloadModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + //Console.WriteLine("Creating Texture download module"); + m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); + m_thread.Name = "ProcessTextureSenderThread"; + m_thread.IsBackground = true; + m_thread.Start(); + ThreadTracker.Add(m_thread); + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence; + } + } + + /// + /// Cleanup the texture service related objects for the removed presence. + /// + /// + private void EventManager_OnRemovePresence(LLUUID agentId) + { + UserTextureDownloadService textureService; + + lock (m_userTextureServices) + { + if (m_userTextureServices.TryGetValue(agentId, out textureService)) + { + textureService.Close(); + + m_userTextureServices.Remove(agentId); + } + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "TextureDownloadModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnRequestTexture += TextureRequest; + } + + /// + /// Does this user have a registered texture download service? + /// + /// + /// + /// Always returns true, since a service is created if one does not already exist + private bool TryGetUserTextureService( + IClientAPI client, out UserTextureDownloadService textureService) + { + lock (m_userTextureServices) + { + if (m_userTextureServices.TryGetValue(client.AgentId, out textureService)) + { + return true; + } + + textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders); + m_userTextureServices.Add(client.AgentId, textureService); + + return true; + } + } + + /// + /// Start the process of requesting a given texture. + /// + /// + /// + public void TextureRequest(Object sender, TextureRequestArgs e) + { + IClientAPI client = (IClientAPI) sender; + UserTextureDownloadService textureService; + + if (TryGetUserTextureService(client, out textureService)) + { + textureService.HandleTextureRequest(e); + } + } + + /// + /// Entry point for the thread dedicated to processing the texture queue. + /// + public void ProcessTextureSenders() + { + ITextureSender sender = null; + + while (true) + { + sender = m_queueSenders.Dequeue(); + + if (sender.Cancel) + { + TextureSent(sender); + + sender.Cancel = false; + } + else + { + bool finished = sender.SendTexturePacket(); + if (finished) + { + TextureSent(sender); + } + else + { + m_queueSenders.Enqueue(sender); + } + } + + // Make sure that any sender we currently have can get garbage collected + sender = null; + + //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count()); + } + } + + /// + /// Called when the texture has finished sending. + /// + /// + private void TextureSent(ITextureSender sender) + { + sender.Sending = false; + //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID); + m_scene.AddPendingDownloads(-1); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/TextureNotFoundSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs similarity index 95% rename from OpenSim/Region/Environment/Modules/TextureNotFoundSender.cs rename to OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs index 7b835a14b9..6f11f7340d 100644 --- a/OpenSim/Region/Environment/Modules/TextureNotFoundSender.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs @@ -1,93 +1,93 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using libsecondlife.Packets; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules -{ - /// - /// Sends a 'texture not found' packet back to the client - /// - public class TextureNotFoundSender : ITextureSender - { - //private static readonly log4net.ILog m_log - // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - private LLUUID m_textureId; - private IClientAPI m_client; - - // See ITextureSender - public bool Sending - { - get { return false; } - set { m_sending = value; } - } - - private bool m_sending = false; - - // See ITextureSender - public bool Cancel - { - get { return false; } - set { m_cancel = value; } - } - - private bool m_cancel = false; - - public TextureNotFoundSender(IClientAPI client, LLUUID textureID) - { - m_client = client; - m_textureId = textureID; - } - - // See ITextureSender - public void UpdateRequest(int discardLevel, uint packetNumber) - { - // Not need to implement since priority changes don't affect this operation - } - - // See ITextureSender - public bool SendTexturePacket() - { - //m_log.InfoFormat( - // "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found", - // m_textureId); - - ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket(); - notFound.ImageID.ID = m_textureId; - - // XXX Temporarily disabling as this appears to be causing client crashes on at least - // 1.19.0(5) of the Linden Second Life client. - // m_client.OutPacket(notFound, ThrottleOutPacketType.Texture); - - return true; - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload +{ + /// + /// Sends a 'texture not found' packet back to the client + /// + public class TextureNotFoundSender : ITextureSender + { + //private static readonly log4net.ILog m_log + // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private LLUUID m_textureId; + private IClientAPI m_client; + + // See ITextureSender + public bool Sending + { + get { return false; } + set { m_sending = value; } + } + + private bool m_sending = false; + + // See ITextureSender + public bool Cancel + { + get { return false; } + set { m_cancel = value; } + } + + private bool m_cancel = false; + + public TextureNotFoundSender(IClientAPI client, LLUUID textureID) + { + m_client = client; + m_textureId = textureID; + } + + // See ITextureSender + public void UpdateRequest(int discardLevel, uint packetNumber) + { + // Not need to implement since priority changes don't affect this operation + } + + // See ITextureSender + public bool SendTexturePacket() + { + //m_log.InfoFormat( + // "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found", + // m_textureId); + + ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket(); + notFound.ImageID.ID = m_textureId; + + // XXX Temporarily disabling as this appears to be causing client crashes on at least + // 1.19.0(5) of the Linden Second Life client. + // m_client.OutPacket(notFound, ThrottleOutPacketType.Texture); + + return true; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs similarity index 90% rename from OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs rename to OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs index e46bf6df86..08a22d6782 100644 --- a/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs @@ -1,250 +1,252 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Limit; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - /// - /// This module sets up texture senders in response to client texture requests, and places them on a - /// processing queue once those senders have the appropriate data (i.e. a texture retrieved from the - /// asset cache). - /// - public class UserTextureDownloadService - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// We will allow the client to request the same texture n times before dropping further requests - /// - /// This number includes repeated requests for the same texture at different resolutions (which we don't - /// currently handle properly as far as I know). However, this situation should be handled in a more - /// sophisticated way. - /// - private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5; - - /// - /// We're going to limit requests for the same missing texture. - /// XXX This is really a temporary solution to deal with the situation where a client continually requests - /// the same missing textures - /// - private readonly IRequestLimitStrategy missingTextureLimitStrategy - = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); - - /// - /// XXX Also going to limit requests for found textures. - /// - private readonly IRequestLimitStrategy foundTextureLimitStrategy - = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); - - /// - /// Holds texture senders before they have received the appropriate texture from the asset cache. - /// - private readonly Dictionary m_textureSenders = new Dictionary(); - - /// - /// Texture Senders are placed in this queue once they have received their texture from the asset - /// cache. Another module actually invokes the send. - /// - private readonly BlockingQueue m_sharedSendersQueue; - - private readonly Scene m_scene; - - private readonly IClientAPI m_client; - - public UserTextureDownloadService( - IClientAPI client, Scene scene, BlockingQueue sharedQueue) - { - m_client = client; - m_scene = scene; - m_sharedSendersQueue = sharedQueue; - } - - /// - /// Handle a texture request. This involves creating a texture sender and placing it on the - /// previously passed in shared queue. - /// - /// - public void HandleTextureRequest(TextureRequestArgs e) - { - TextureSender textureSender; - - //TODO: should be working out the data size/ number of packets to be sent for each discard level - if ((e.DiscardLevel >= 0) || (e.Priority != 0)) - { - lock (m_textureSenders) - { - if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) - { - // If we've received new non UUID information for this request and it hasn't dispatched - // yet, then update the request accordingly. - textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); - } - else - { - if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) - { -// m_log.DebugFormat( -// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}", -// e.RequestedAssetID, m_client.AgentId); - - return; - } - else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) - { - if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID)) - { - // Commenting out this message for now as it causes too much noise with other - // debug messages. - // TODO: possibly record this as a statistic in the future - // -// m_log.DebugFormat( -// "[USER TEXTURE DOWNLOAD SERVICE]: Dropping requests for notified missing texture {0} for client {1} since we have received more than {2} requests", -// e.RequestedAssetID, m_client.AgentId, MAX_ALLOWED_TEXTURE_REQUESTS); - } - - return; - } - - m_scene.AddPendingDownloads(1); - - TextureSender requestHandler = new TextureSender(m_client, e.DiscardLevel, e.PacketNumber); - m_textureSenders.Add(e.RequestedAssetID, requestHandler); - - m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); - } - } - } - else - { - lock (m_textureSenders) - { - if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) - { - textureSender.Cancel = true; - } - } - } - } - - /// - /// The callback for the asset cache when a texture has been retrieved. This method queues the - /// texture sender for processing. - /// - /// - /// - public void TextureCallback(LLUUID textureID, AssetBase texture) - { - //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false)); - - lock (m_textureSenders) - { - TextureSender textureSender; - - if (m_textureSenders.TryGetValue(textureID, out textureSender)) - { - // XXX It may be perfectly valid for a texture to have no data... but if we pass - // this on to the TextureSender it will blow up, so just discard for now. - // Needs investigation. - if (texture == null || texture.Data == null) - { - if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID)) - { - missingTextureLimitStrategy.MonitorRequests(textureID); - - m_log.DebugFormat( - "[USER TEXTURE DOWNLOAD SERVICE]: Queueing first TextureNotFoundSender for {0}, client {1}", - textureID, m_client.AgentId); - } - - ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID); - EnqueueTextureSender(textureNotFoundSender); - } - else - { - if (!textureSender.ImageLoaded) - { - textureSender.TextureReceived(texture); - EnqueueTextureSender(textureSender); - - foundTextureLimitStrategy.MonitorRequests(textureID); - } - } - - //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID); - m_textureSenders.Remove(textureID); - //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count); - } - else - { - m_log.WarnFormat( - "Got a texture uuid {0} with no sender object to handle it, this shouldn't happen", - textureID); - } - } - } - - /// - /// Place a ready texture sender on the processing queue. - /// - /// - private void EnqueueTextureSender(ITextureSender textureSender) - { - textureSender.Cancel = false; - textureSender.Sending = true; - - if (!m_sharedSendersQueue.Contains(textureSender)) - { - m_sharedSendersQueue.Enqueue(textureSender); - } - } - - /// - /// Close this module. - /// - internal void Close() - { - lock (m_textureSenders) - { - foreach( TextureSender textureSender in m_textureSenders.Values ) - { - textureSender.Cancel = true; - } - - m_textureSenders.Clear(); - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Limit; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules.Agent.TextureDownload; +using OpenSim.Region.Environment.Modules.Agent.TextureSender; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload +{ + /// + /// This module sets up texture senders in response to client texture requests, and places them on a + /// processing queue once those senders have the appropriate data (i.e. a texture retrieved from the + /// asset cache). + /// + public class UserTextureDownloadService + { + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// We will allow the client to request the same texture n times before dropping further requests + /// + /// This number includes repeated requests for the same texture at different resolutions (which we don't + /// currently handle properly as far as I know). However, this situation should be handled in a more + /// sophisticated way. + /// + private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5; + + /// + /// We're going to limit requests for the same missing texture. + /// XXX This is really a temporary solution to deal with the situation where a client continually requests + /// the same missing textures + /// + private readonly IRequestLimitStrategy missingTextureLimitStrategy + = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); + + /// + /// XXX Also going to limit requests for found textures. + /// + private readonly IRequestLimitStrategy foundTextureLimitStrategy + = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); + + /// + /// Holds texture senders before they have received the appropriate texture from the asset cache. + /// + private readonly Dictionary m_textureSenders = new Dictionary(); + + /// + /// Texture Senders are placed in this queue once they have received their texture from the asset + /// cache. Another module actually invokes the send. + /// + private readonly BlockingQueue m_sharedSendersQueue; + + private readonly Scene m_scene; + + private readonly IClientAPI m_client; + + public UserTextureDownloadService( + IClientAPI client, Scene scene, BlockingQueue sharedQueue) + { + m_client = client; + m_scene = scene; + m_sharedSendersQueue = sharedQueue; + } + + /// + /// Handle a texture request. This involves creating a texture sender and placing it on the + /// previously passed in shared queue. + /// + /// + public void HandleTextureRequest(TextureRequestArgs e) + { + TextureSender.TextureSender textureSender; + + //TODO: should be working out the data size/ number of packets to be sent for each discard level + if ((e.DiscardLevel >= 0) || (e.Priority != 0)) + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + // If we've received new non UUID information for this request and it hasn't dispatched + // yet, then update the request accordingly. + textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); + } + else + { + if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) + { +// m_log.DebugFormat( +// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}", +// e.RequestedAssetID, m_client.AgentId); + + return; + } + else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) + { + if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID)) + { + // Commenting out this message for now as it causes too much noise with other + // debug messages. + // TODO: possibly record this as a statistic in the future + // +// m_log.DebugFormat( +// "[USER TEXTURE DOWNLOAD SERVICE]: Dropping requests for notified missing texture {0} for client {1} since we have received more than {2} requests", +// e.RequestedAssetID, m_client.AgentId, MAX_ALLOWED_TEXTURE_REQUESTS); + } + + return; + } + + m_scene.AddPendingDownloads(1); + + TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber); + m_textureSenders.Add(e.RequestedAssetID, requestHandler); + + m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); + } + } + } + else + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + textureSender.Cancel = true; + } + } + } + } + + /// + /// The callback for the asset cache when a texture has been retrieved. This method queues the + /// texture sender for processing. + /// + /// + /// + public void TextureCallback(LLUUID textureID, AssetBase texture) + { + //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false)); + + lock (m_textureSenders) + { + TextureSender.TextureSender textureSender; + + if (m_textureSenders.TryGetValue(textureID, out textureSender)) + { + // XXX It may be perfectly valid for a texture to have no data... but if we pass + // this on to the TextureSender it will blow up, so just discard for now. + // Needs investigation. + if (texture == null || texture.Data == null) + { + if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID)) + { + missingTextureLimitStrategy.MonitorRequests(textureID); + + m_log.DebugFormat( + "[USER TEXTURE DOWNLOAD SERVICE]: Queueing first TextureNotFoundSender for {0}, client {1}", + textureID, m_client.AgentId); + } + + ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID); + EnqueueTextureSender(textureNotFoundSender); + } + else + { + if (!textureSender.ImageLoaded) + { + textureSender.TextureReceived(texture); + EnqueueTextureSender(textureSender); + + foundTextureLimitStrategy.MonitorRequests(textureID); + } + } + + //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID); + m_textureSenders.Remove(textureID); + //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count); + } + else + { + m_log.WarnFormat( + "Got a texture uuid {0} with no sender object to handle it, this shouldn't happen", + textureID); + } + } + } + + /// + /// Place a ready texture sender on the processing queue. + /// + /// + private void EnqueueTextureSender(ITextureSender textureSender) + { + textureSender.Cancel = false; + textureSender.Sending = true; + + if (!m_sharedSendersQueue.Contains(textureSender)) + { + m_sharedSendersQueue.Enqueue(textureSender); + } + } + + /// + /// Close this module. + /// + internal void Close() + { + lock (m_textureSenders) + { + foreach( TextureSender.TextureSender textureSender in m_textureSenders.Values ) + { + textureSender.Cancel = true; + } + + m_textureSenders.Clear(); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/TextureSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs similarity index 96% rename from OpenSim/Region/Environment/Modules/TextureSender.cs rename to OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs index e54a1a214d..37b0652cd9 100644 --- a/OpenSim/Region/Environment/Modules/TextureSender.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs @@ -1,220 +1,220 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife.Packets; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules -{ - /// - /// A TextureSender handles the process of receiving a texture requested by the client from the - /// AssetCache, and then sending that texture back to the client. - /// - public class TextureSender : ITextureSender - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Records the number of times texture send has been called. - /// - public int counter = 0; - - /// - /// Holds the texture asset to send. - /// - private AssetBase m_asset; - - //public LLUUID assetID { get { return m_asset.FullID; } } - - /// - /// This is actually the number of extra packets required to send the texture data! We always assume - /// at least one is required. - /// - private int NumPackets = 0; - - /// - /// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts - /// at the 600th byte (0th indexed). - /// - private int PacketCounter = 0; - - // See ITextureSender - public bool Cancel - { - get { return false; } - set { m_cancel = value; } - } - - private bool m_cancel = false; - - // See ITextureSender - public bool Sending - { - get { return false; } - set { m_sending = value; } - } - - private bool m_sending = false; - - public bool ImageLoaded = false; - - private IClientAPI RequestUser; - - private int RequestedDiscardLevel = -1; - private uint StartPacketNumber = 0; - - public TextureSender(IClientAPI client, int discardLevel, uint packetNumber) - { - RequestUser = client; - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; - } - - /// - /// Load up the texture data to send. - /// - /// - /// A - /// - public void TextureReceived(AssetBase asset) - { - m_asset = asset; - NumPackets = CalculateNumPackets(asset.Data.Length); - PacketCounter = (int) StartPacketNumber; - ImageLoaded = true; - } - - // See ITextureSender - public void UpdateRequest(int discardLevel, uint packetNumber) - { - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; - PacketCounter = (int) StartPacketNumber; - } - - // See ITextureSender - public bool SendTexturePacket() - { - //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID); - - SendPacket(); - counter++; - if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || - ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1))))) - { - return true; - } - return false; - } - - /// - /// Sends a texture packet to the client. - /// - private void SendPacket() - { - if (PacketCounter <= NumPackets) - { - if (PacketCounter == 0) - { - if (NumPackets == 0) - { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = 1; - im.ImageID.ID = m_asset.FullID; - im.ImageID.Size = (uint) m_asset.Data.Length; - im.ImageData.Data = m_asset.Data; - im.ImageID.Codec = 2; - RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); - PacketCounter++; - } - else - { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = (ushort) (NumPackets); - im.ImageID.ID = m_asset.FullID; - im.ImageID.Size = (uint) m_asset.Data.Length; - im.ImageData.Data = new byte[600]; - Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); - im.ImageID.Codec = 2; - RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); - PacketCounter++; - } - } - else - { - ImagePacketPacket im = new ImagePacketPacket(); - im.Header.Reliable = false; - im.ImageID.Packet = (ushort) (PacketCounter); - im.ImageID.ID = m_asset.FullID; - int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1)); - if (size > 1000) size = 1000; - im.ImageData.Data = new byte[size]; - try - { - Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size); - } - catch (ArgumentOutOfRangeException) - { - m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" + - m_asset.FullID.ToString() ); - return; - } - RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); - PacketCounter++; - } - } - } - - /// - /// Calculate the number of packets that will be required to send the texture loaded into this sender - /// This is actually the number of 1000 byte packets not including an initial 600 byte packet... - /// - /// - /// - private int CalculateNumPackets(int length) - { - int numPackets = 0; - - if (length > 600) - { - //over 600 bytes so split up file - int restData = (length - 600); - int restPackets = ((restData + 999)/1000); - numPackets = restPackets; - } - - return numPackets; - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife.Packets; +using log4net; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment.Modules.Agent.TextureSender +{ + /// + /// A TextureSender handles the process of receiving a texture requested by the client from the + /// AssetCache, and then sending that texture back to the client. + /// + public class TextureSender : ITextureSender + { + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Records the number of times texture send has been called. + /// + public int counter = 0; + + /// + /// Holds the texture asset to send. + /// + private AssetBase m_asset; + + //public LLUUID assetID { get { return m_asset.FullID; } } + + /// + /// This is actually the number of extra packets required to send the texture data! We always assume + /// at least one is required. + /// + private int NumPackets = 0; + + /// + /// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts + /// at the 600th byte (0th indexed). + /// + private int PacketCounter = 0; + + // See ITextureSender + public bool Cancel + { + get { return false; } + set { m_cancel = value; } + } + + private bool m_cancel = false; + + // See ITextureSender + public bool Sending + { + get { return false; } + set { m_sending = value; } + } + + private bool m_sending = false; + + public bool ImageLoaded = false; + + private IClientAPI RequestUser; + + private int RequestedDiscardLevel = -1; + private uint StartPacketNumber = 0; + + public TextureSender(IClientAPI client, int discardLevel, uint packetNumber) + { + RequestUser = client; + RequestedDiscardLevel = discardLevel; + StartPacketNumber = packetNumber; + } + + /// + /// Load up the texture data to send. + /// + /// + /// A + /// + public void TextureReceived(AssetBase asset) + { + m_asset = asset; + NumPackets = CalculateNumPackets(asset.Data.Length); + PacketCounter = (int) StartPacketNumber; + ImageLoaded = true; + } + + // See ITextureSender + public void UpdateRequest(int discardLevel, uint packetNumber) + { + RequestedDiscardLevel = discardLevel; + StartPacketNumber = packetNumber; + PacketCounter = (int) StartPacketNumber; + } + + // See ITextureSender + public bool SendTexturePacket() + { + //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID); + + SendPacket(); + counter++; + if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || + ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1))))) + { + return true; + } + return false; + } + + /// + /// Sends a texture packet to the client. + /// + private void SendPacket() + { + if (PacketCounter <= NumPackets) + { + if (PacketCounter == 0) + { + if (NumPackets == 0) + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = 1; + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint) m_asset.Data.Length; + im.ImageData.Data = m_asset.Data; + im.ImageID.Codec = 2; + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + else + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = (ushort) (NumPackets); + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint) m_asset.Data.Length; + im.ImageData.Data = new byte[600]; + Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); + im.ImageID.Codec = 2; + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + } + else + { + ImagePacketPacket im = new ImagePacketPacket(); + im.Header.Reliable = false; + im.ImageID.Packet = (ushort) (PacketCounter); + im.ImageID.ID = m_asset.FullID; + int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1)); + if (size > 1000) size = 1000; + im.ImageData.Data = new byte[size]; + try + { + Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size); + } + catch (ArgumentOutOfRangeException) + { + m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" + + m_asset.FullID.ToString() ); + return; + } + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + } + } + + /// + /// Calculate the number of packets that will be required to send the texture loaded into this sender + /// This is actually the number of 1000 byte packets not including an initial 600 byte packet... + /// + /// + /// + private int CalculateNumPackets(int length) + { + int numPackets = 0; + + if (length > 600) + { + //over 600 bytes so split up file + int restData = (length - 600); + int restPackets = ((restData + 999)/1000); + numPackets = restPackets; + } + + return numPackets; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/XferModule.cs b/OpenSim/Region/Environment/Modules/Agent/Xfer/XferModule.cs similarity index 96% rename from OpenSim/Region/Environment/Modules/XferModule.cs rename to OpenSim/Region/Environment/Modules/Agent/Xfer/XferModule.cs index 87bc1c5974..b609f930a1 100644 --- a/OpenSim/Region/Environment/Modules/XferModule.cs +++ b/OpenSim/Region/Environment/Modules/Agent/Xfer/XferModule.cs @@ -1,225 +1,225 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class XferModule : IRegionModule, IXfer - { - public Dictionary NewFiles = new Dictionary(); - public Dictionary Transfers = new Dictionary(); - - private Scene m_scene; - - public XferModule() - { - } - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_scene.EventManager.OnNewClient += NewClient; - - m_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "XferModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void NewClient(IClientAPI client) - { - client.OnRequestXfer += RequestXfer; - client.OnConfirmXfer += AckPacket; - } - - /// - /// - /// - /// - /// - /// - public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName) - { - lock (NewFiles) - { - if (NewFiles.ContainsKey(fileName)) - { - if (!Transfers.ContainsKey(xferID)) - { - byte[] fileData = NewFiles[fileName]; - XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); - Transfers.Add(xferID, transaction); - NewFiles.Remove(fileName); - - if (transaction.StartSend()) - { - Transfers.Remove(xferID); - } - } - } - } - } - - public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) - { - if (Transfers.ContainsKey(xferID)) - { - if (Transfers[xferID].AckPacket(packet)) - { - { - Transfers.Remove(xferID); - } - } - } - } - - public bool AddNewFile(string fileName, byte[] data) - { - lock (NewFiles) - { - if (NewFiles.ContainsKey(fileName)) - { - NewFiles[fileName] = data; - } - else - { - NewFiles.Add(fileName, data); - } - } - return true; - } - - - public class XferDownLoad - { - public byte[] Data = new byte[0]; - public string FileName = String.Empty; - public ulong XferID = 0; - public int DataPointer = 0; - public uint Packet = 0; - public IClientAPI Client; - public uint Serial = 1; - private bool complete; - - public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) - { - FileName = fileName; - Data = data; - XferID = xferID; - Client = client; - } - - public XferDownLoad() - { - } - - /// - /// Start a transfer - /// - /// True if the transfer is complete, false if not - public bool StartSend() - { - if (Data.Length < 1000) - { - // for now (testing ) we only support files under 1000 bytes - byte[] transferData = new byte[Data.Length + 4]; - Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); - Array.Copy(Data, 0, transferData, 4, Data.Length); - Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); - - complete = true; - } - else - { - byte[] transferData = new byte[1000 + 4]; - Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); - Array.Copy(Data, 0, transferData, 4, 1000); - Client.SendXferPacket(XferID, 0, transferData); - Packet++; - DataPointer = 1000; - } - - return complete; - } - - /// - /// Respond to an ack packet from the client - /// - /// - /// True if the transfer is complete, false otherwise - public bool AckPacket(uint packet) - { - if (!complete) - { - if ((Data.Length - DataPointer) > 1000) - { - byte[] transferData = new byte[1000]; - Array.Copy(Data, DataPointer, transferData, 0, 1000); - Client.SendXferPacket(XferID, Packet, transferData); - Packet++; - DataPointer += 1000; - } - else - { - byte[] transferData = new byte[Data.Length - DataPointer]; - Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); - uint endPacket = Packet |= (uint) 0x80000000; - Client.SendXferPacket(XferID, endPacket, transferData); - Packet++; - DataPointer += (Data.Length - DataPointer); - - complete = true; - } - } - - return complete; - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Agent.Xfer +{ + public class XferModule : IRegionModule, IXfer + { + public Dictionary NewFiles = new Dictionary(); + public Dictionary Transfers = new Dictionary(); + + private Scene m_scene; + + public XferModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "XferModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnRequestXfer += RequestXfer; + client.OnConfirmXfer += AckPacket; + } + + /// + /// + /// + /// + /// + /// + public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName) + { + lock (NewFiles) + { + if (NewFiles.ContainsKey(fileName)) + { + if (!Transfers.ContainsKey(xferID)) + { + byte[] fileData = NewFiles[fileName]; + XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); + Transfers.Add(xferID, transaction); + NewFiles.Remove(fileName); + + if (transaction.StartSend()) + { + Transfers.Remove(xferID); + } + } + } + } + } + + public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) + { + if (Transfers.ContainsKey(xferID)) + { + if (Transfers[xferID].AckPacket(packet)) + { + { + Transfers.Remove(xferID); + } + } + } + } + + public bool AddNewFile(string fileName, byte[] data) + { + lock (NewFiles) + { + if (NewFiles.ContainsKey(fileName)) + { + NewFiles[fileName] = data; + } + else + { + NewFiles.Add(fileName, data); + } + } + return true; + } + + + public class XferDownLoad + { + public byte[] Data = new byte[0]; + public string FileName = String.Empty; + public ulong XferID = 0; + public int DataPointer = 0; + public uint Packet = 0; + public IClientAPI Client; + public uint Serial = 1; + private bool complete; + + public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) + { + FileName = fileName; + Data = data; + XferID = xferID; + Client = client; + } + + public XferDownLoad() + { + } + + /// + /// Start a transfer + /// + /// True if the transfer is complete, false if not + public bool StartSend() + { + if (Data.Length < 1000) + { + // for now (testing ) we only support files under 1000 bytes + byte[] transferData = new byte[Data.Length + 4]; + Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); + Array.Copy(Data, 0, transferData, 4, Data.Length); + Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); + + complete = true; + } + else + { + byte[] transferData = new byte[1000 + 4]; + Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); + Array.Copy(Data, 0, transferData, 4, 1000); + Client.SendXferPacket(XferID, 0, transferData); + Packet++; + DataPointer = 1000; + } + + return complete; + } + + /// + /// Respond to an ack packet from the client + /// + /// + /// True if the transfer is complete, false otherwise + public bool AckPacket(uint packet) + { + if (!complete) + { + if ((Data.Length - DataPointer) > 1000) + { + byte[] transferData = new byte[1000]; + Array.Copy(Data, DataPointer, transferData, 0, 1000); + Client.SendXferPacket(XferID, Packet, transferData); + Packet++; + DataPointer += 1000; + } + else + { + byte[] transferData = new byte[Data.Length - DataPointer]; + Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); + uint endPacket = Packet |= (uint) 0x80000000; + Client.SendXferPacket(XferID, endPacket, transferData); + Packet++; + DataPointer += (Data.Length - DataPointer); + + complete = true; + } + } + + return complete; + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/AppearanceTableMapper.cs b/OpenSim/Region/Environment/Modules/AppearanceTableMapper.cs deleted file mode 100644 index 53539526fc..0000000000 --- a/OpenSim/Region/Environment/Modules/AppearanceTableMapper.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.Generic; -using System.Text; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Framework; -using OpenSim.Data.Base; - -namespace OpenSim.Region.Environment.Modules -{ - - public class AppearanceRowMapper : BaseRowMapper - { - public AppearanceRowMapper(BaseSchema schema, AvatarAppearance obj) - : base(schema, obj) - { - } - } - - public class AppearanceTableMapper : BaseTableMapper - { - public AppearanceTableMapper(BaseDatabaseConnector database, string tableName) - : base(database, tableName) - { - BaseSchema rowMapperSchema = new BaseSchema(this); - m_schema = rowMapperSchema; - - m_keyFieldMapper = rowMapperSchema.AddMapping("UUID", - delegate(AppearanceRowMapper mapper) { return mapper.Object.ScenePresenceID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.ScenePresenceID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("Serial", - delegate(AppearanceRowMapper mapper) { return (uint)mapper.Object.WearablesSerial; }, - delegate(AppearanceRowMapper mapper, uint value) { mapper.Object.WearablesSerial = (int)value; }); - - rowMapperSchema.AddMapping("WearableItem0", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[0].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { - if (mapper.Object.Wearables == null) - { - mapper.Object.Wearables = new OpenSim.Framework.AvatarWearable[13]; - for (int i = 0; i < 13; i++) - { - mapper.Object.Wearables[i] = new AvatarWearable(); - } - } - mapper.Object.Wearables[0].ItemID = new libsecondlife.LLUUID(value.ToString()); - }); - - rowMapperSchema.AddMapping("WearableAsset0", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[0].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[0].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem1", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[1].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[1].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset1", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[1].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[1].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem2", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[2].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[2].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset2", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[2].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[2].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem3", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[3].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[3].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset3", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[3].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[3].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem4", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[4].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[4].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset4", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[4].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[4].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem5", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[5].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[5].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset5", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[5].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[5].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem6", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[6].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[6].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset6", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[6].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[6].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem7", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[7].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[7].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset7", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[7].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[7].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem8", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[8].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[8].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset8", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[8].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[8].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem9", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[9].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[9].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset9", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[9].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[9].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem10", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[10].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[10].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset10", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[10].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[10].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem11", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[11].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[11].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset11", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[11].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[11].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableItem12", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[12].ItemID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[12].ItemID = new libsecondlife.LLUUID(value.ToString()); }); - - rowMapperSchema.AddMapping("WearableAsset12", - delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[12].AssetID.UUID; }, - delegate(AppearanceRowMapper mapper, Guid value) - { mapper.Object.Wearables[12].AssetID = new libsecondlife.LLUUID(value.ToString()); }); - - } - - public bool Add(Guid userID, AvatarAppearance appearance) - { - AppearanceRowMapper mapper = CreateRowMapper(appearance); - return Add(mapper); - } - - public bool Update(Guid userID, AvatarAppearance appearance) - { - AppearanceRowMapper mapper = CreateRowMapper(appearance); - return Update(appearance.ScenePresenceID.UUID, mapper); - } - - protected AppearanceRowMapper CreateRowMapper(AvatarAppearance appearance) - { - return new AppearanceRowMapper(m_schema, appearance); - } - - protected AppearanceRowMapper CreateRowMapper() - { - return CreateRowMapper(new AvatarAppearance()); - } - - protected AppearanceRowMapper FromReader(BaseDataReader reader, AvatarAppearance appearance) - { - AppearanceRowMapper mapper = CreateRowMapper(appearance); - mapper.FillObject(reader); - return mapper; - } - - public override AppearanceRowMapper FromReader(BaseDataReader reader) - { - AppearanceRowMapper mapper = CreateRowMapper(); - mapper.FillObject(reader); - return mapper; - } - - public bool TryGetValue(Guid presenceID, out AvatarAppearance val) - { - AppearanceRowMapper mapper; - if (TryGetValue(presenceID, out mapper)) - { - val = mapper.Object; - return true; - } - else - { - val = null; - return false; - } - } - } - -}*/ diff --git a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs similarity index 97% rename from OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs index cb94021086..3614686e28 100644 --- a/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -1,338 +1,338 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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.Threading; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Data.MySQLMapper; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Data.Base; - -namespace OpenSim.Region.Environment.Modules -{ - public class AvatarFactoryModule : IAvatarFactory - { - private Scene m_scene = null; - private readonly Dictionary m_avatarsAppearance = new Dictionary(); - - private bool m_enablePersist = false; - private string m_connectionString; - private bool m_configured = false; - private BaseDatabaseConnector m_databaseMapper; - private AppearanceTableMapper m_appearanceMapper; - - private Dictionary m_fetchesInProgress = new Dictionary(); - private object m_syncLock = new object(); - - public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance) - { - - //should only let one thread at a time do this part - EventWaitHandle waitHandle = null; - bool fetchInProgress = false; - lock (m_syncLock) - { - appearance = CheckCache(avatarId); - if (appearance != null) - { - return true; - } - - //not in cache so check to see if another thread is already fetching it - if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle)) - { - fetchInProgress = true; - } - else - { - fetchInProgress = false; - - //no thread already fetching this appearance, so add a wait handle to list - //for any following threads that want the same appearance - waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); - m_fetchesInProgress.Add(avatarId, waitHandle); - } - } - - if (fetchInProgress) - { - waitHandle.WaitOne(); - appearance = CheckCache(avatarId); - if (appearance != null) - { - waitHandle = null; - return true; - } - else - { - waitHandle = null; - return false; - } - } - else - { - Thread.Sleep(5000); - - //this is the first thread to request this appearance - //so let it check the db and if not found then create a default appearance - //and add that to the cache - appearance = CheckDatabase(avatarId); - if (appearance != null) - { - //appearance has now been added to cache so lets pulse any waiting threads - lock (m_syncLock) - { - m_fetchesInProgress.Remove(avatarId); - waitHandle.Set(); - } - // waitHandle.Close(); - waitHandle = null; - return true; - } - - //not found a appearance for the user, so create a new default one - appearance = CreateDefault(avatarId); - if (appearance != null) - { - //update database - if (m_enablePersist) - { - m_appearanceMapper.Add(avatarId.UUID, appearance); - } - - //add appearance to dictionary cache - lock (m_avatarsAppearance) - { - m_avatarsAppearance[avatarId] = appearance; - } - - //appearance has now been added to cache so lets pulse any waiting threads - lock (m_syncLock) - { - m_fetchesInProgress.Remove(avatarId); - waitHandle.Set(); - } - // waitHandle.Close(); - waitHandle = null; - return true; - } - else - { - //something went wrong, so release the wait handle and remove it - //all waiting threads will fail to find cached appearance - //but its better for them to fail than wait for ever - lock (m_syncLock) - { - m_fetchesInProgress.Remove(avatarId); - waitHandle.Set(); - } - //waitHandle.Close(); - waitHandle = null; - return false; - } - } - } - - private AvatarAppearance CreateDefault(LLUUID avatarId) - { - AvatarAppearance appearance = null; - AvatarWearable[] wearables; - byte[] visualParams; - GetDefaultAvatarAppearance(out wearables, out visualParams); - appearance = new AvatarAppearance(avatarId, wearables, visualParams); - - return appearance; - } - - private AvatarAppearance CheckDatabase(LLUUID avatarId) - { - AvatarAppearance appearance = null; - if (m_enablePersist) - { - if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance)) - { - appearance.VisualParams = GetDefaultVisualParams(); - appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry(); - lock (m_avatarsAppearance) - { - m_avatarsAppearance[avatarId] = appearance; - } - } - } - return appearance; - } - - private AvatarAppearance CheckCache(LLUUID avatarId) - { - AvatarAppearance appearance = null; - lock (m_avatarsAppearance) - { - if (m_avatarsAppearance.ContainsKey(avatarId)) - { - appearance = m_avatarsAppearance[avatarId]; - } - } - return appearance; - } - - public void Initialise(Scene scene, IConfigSource source) - { - scene.RegisterModuleInterface(this); - scene.EventManager.OnNewClient += NewClient; - - if (m_scene == null) - { - m_scene = scene; - } - - if (!m_configured) - { - m_configured = true; - try - { - m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false); - m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", ""); - } - catch (Exception) - { - } - if (m_enablePersist) - { - m_databaseMapper = new MySQLDatabaseMapper(m_connectionString); - m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance"); - } - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "Default Avatar Factory"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public void NewClient(IClientAPI client) - { - client.OnAvatarNowWearing += AvatarIsWearing; - } - - public void RemoveClient(IClientAPI client) - { - // client.OnAvatarNowWearing -= AvatarIsWearing; - } - - public void AvatarIsWearing(Object sender, AvatarWearingArgs e) - { - IClientAPI clientView = (IClientAPI)sender; - CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId); - if (profile != null) - { - if (profile.RootFolder != null) - { - if (m_avatarsAppearance.ContainsKey(clientView.AgentId)) - { - AvatarAppearance avatAppearance = null; - lock (m_avatarsAppearance) - { - avatAppearance = m_avatarsAppearance[clientView.AgentId]; - } - - foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) - { - if (wear.Type < 13) - { - if (wear.ItemID == LLUUID.Zero) - { - avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero; - avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero; - - UpdateDatabase(clientView.AgentId, avatAppearance); - } - else - { - LLUUID assetId; - - InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID); - if (baseItem != null) - { - assetId = baseItem.assetID; - avatAppearance.Wearables[wear.Type].AssetID = assetId; - avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; - - UpdateDatabase(clientView.AgentId, avatAppearance); - } - } - } - } - } - } - } - } - - public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance) - { - if (m_enablePersist) - { - m_appearanceMapper.Update(userID.UUID, avatAppearance); - } - } - - public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) - { - visualParams = GetDefaultVisualParams(); - wearables = AvatarWearable.DefaultWearables; - } - - private static byte[] GetDefaultVisualParams() - { - byte[] visualParams; - visualParams = new byte[218]; - for (int i = 0; i < 218; i++) - { - visualParams[i] = 100; - } - return visualParams; - } - } -}*/ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Data.MySQLMapper; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Data.Base; + +namespace OpenSim.Region.Environment.Modules +{ + public class AvatarFactoryModule : IAvatarFactory + { + private Scene m_scene = null; + private readonly Dictionary m_avatarsAppearance = new Dictionary(); + + private bool m_enablePersist = false; + private string m_connectionString; + private bool m_configured = false; + private BaseDatabaseConnector m_databaseMapper; + private AppearanceTableMapper m_appearanceMapper; + + private Dictionary m_fetchesInProgress = new Dictionary(); + private object m_syncLock = new object(); + + public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance) + { + + //should only let one thread at a time do this part + EventWaitHandle waitHandle = null; + bool fetchInProgress = false; + lock (m_syncLock) + { + appearance = CheckCache(avatarId); + if (appearance != null) + { + return true; + } + + //not in cache so check to see if another thread is already fetching it + if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle)) + { + fetchInProgress = true; + } + else + { + fetchInProgress = false; + + //no thread already fetching this appearance, so add a wait handle to list + //for any following threads that want the same appearance + waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); + m_fetchesInProgress.Add(avatarId, waitHandle); + } + } + + if (fetchInProgress) + { + waitHandle.WaitOne(); + appearance = CheckCache(avatarId); + if (appearance != null) + { + waitHandle = null; + return true; + } + else + { + waitHandle = null; + return false; + } + } + else + { + Thread.Sleep(5000); + + //this is the first thread to request this appearance + //so let it check the db and if not found then create a default appearance + //and add that to the cache + appearance = CheckDatabase(avatarId); + if (appearance != null) + { + //appearance has now been added to cache so lets pulse any waiting threads + lock (m_syncLock) + { + m_fetchesInProgress.Remove(avatarId); + waitHandle.Set(); + } + // waitHandle.Close(); + waitHandle = null; + return true; + } + + //not found a appearance for the user, so create a new default one + appearance = CreateDefault(avatarId); + if (appearance != null) + { + //update database + if (m_enablePersist) + { + m_appearanceMapper.Add(avatarId.UUID, appearance); + } + + //add appearance to dictionary cache + lock (m_avatarsAppearance) + { + m_avatarsAppearance[avatarId] = appearance; + } + + //appearance has now been added to cache so lets pulse any waiting threads + lock (m_syncLock) + { + m_fetchesInProgress.Remove(avatarId); + waitHandle.Set(); + } + // waitHandle.Close(); + waitHandle = null; + return true; + } + else + { + //something went wrong, so release the wait handle and remove it + //all waiting threads will fail to find cached appearance + //but its better for them to fail than wait for ever + lock (m_syncLock) + { + m_fetchesInProgress.Remove(avatarId); + waitHandle.Set(); + } + //waitHandle.Close(); + waitHandle = null; + return false; + } + } + } + + private AvatarAppearance CreateDefault(LLUUID avatarId) + { + AvatarAppearance appearance = null; + AvatarWearable[] wearables; + byte[] visualParams; + GetDefaultAvatarAppearance(out wearables, out visualParams); + appearance = new AvatarAppearance(avatarId, wearables, visualParams); + + return appearance; + } + + private AvatarAppearance CheckDatabase(LLUUID avatarId) + { + AvatarAppearance appearance = null; + if (m_enablePersist) + { + if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance)) + { + appearance.VisualParams = GetDefaultVisualParams(); + appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry(); + lock (m_avatarsAppearance) + { + m_avatarsAppearance[avatarId] = appearance; + } + } + } + return appearance; + } + + private AvatarAppearance CheckCache(LLUUID avatarId) + { + AvatarAppearance appearance = null; + lock (m_avatarsAppearance) + { + if (m_avatarsAppearance.ContainsKey(avatarId)) + { + appearance = m_avatarsAppearance[avatarId]; + } + } + return appearance; + } + + public void Initialise(Scene scene, IConfigSource source) + { + scene.RegisterModuleInterface(this); + scene.EventManager.OnNewClient += NewClient; + + if (m_scene == null) + { + m_scene = scene; + } + + if (!m_configured) + { + m_configured = true; + try + { + m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false); + m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", ""); + } + catch (Exception) + { + } + if (m_enablePersist) + { + m_databaseMapper = new MySQLDatabaseMapper(m_connectionString); + m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance"); + } + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "Default Avatar Factory"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + client.OnAvatarNowWearing += AvatarIsWearing; + } + + public void RemoveClient(IClientAPI client) + { + // client.OnAvatarNowWearing -= AvatarIsWearing; + } + + public void AvatarIsWearing(Object sender, AvatarWearingArgs e) + { + IClientAPI clientView = (IClientAPI)sender; + CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId); + if (profile != null) + { + if (profile.RootFolder != null) + { + if (m_avatarsAppearance.ContainsKey(clientView.AgentId)) + { + AvatarAppearance avatAppearance = null; + lock (m_avatarsAppearance) + { + avatAppearance = m_avatarsAppearance[clientView.AgentId]; + } + + foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) + { + if (wear.Type < 13) + { + if (wear.ItemID == LLUUID.Zero) + { + avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero; + avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero; + + UpdateDatabase(clientView.AgentId, avatAppearance); + } + else + { + LLUUID assetId; + + InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID); + if (baseItem != null) + { + assetId = baseItem.assetID; + avatAppearance.Wearables[wear.Type].AssetID = assetId; + avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; + + UpdateDatabase(clientView.AgentId, avatAppearance); + } + } + } + } + } + } + } + } + + public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance) + { + if (m_enablePersist) + { + m_appearanceMapper.Update(userID.UUID, avatAppearance); + } + } + + public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) + { + visualParams = GetDefaultVisualParams(); + wearables = AvatarWearable.DefaultWearables; + } + + 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/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs similarity index 92% rename from OpenSim/Region/Environment/Modules/ChatModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs index 30c13979c8..1281873993 100644 --- a/OpenSim/Region/Environment/Modules/ChatModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs @@ -1,831 +1,831 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class ChatModule : IRegionModule, ISimChat - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private List m_scenes = new List(); - - private int m_whisperdistance = 10; - private int m_saydistance = 30; - private int m_shoutdistance = 100; - - private IRCChatModule m_irc = null; - - private string m_last_new_user = null; - private string m_last_leaving_user = null; - private string m_defaultzone = null; - internal object m_syncInit = new object(); - internal object m_syncLogout = new object(); - private Thread m_irc_connector=null; - - public void Initialise(Scene scene, IConfigSource config) - { - lock (m_syncInit) - { - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - scene.EventManager.OnNewClient += NewClient; - scene.RegisterModuleInterface(this); - } - - // wrap this in a try block so that defaults will work if - // the config file doesn't specify otherwise. - 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); - } - catch (Exception) - { - } - - try - { - m_defaultzone = config.Configs["IRC"].GetString("nick","Sim"); - } - catch (Exception) - { - } - - // setup IRC Relay - if (m_irc == null) { m_irc = new IRCChatModule(config); } - if (m_irc_connector == null) - { - m_irc_connector = new Thread(IRCConnectRun); - m_irc_connector.Name = "IRCConnectorThread"; - m_irc_connector.IsBackground = true; - } - } - } - - public void PostInitialise() - { - if (m_irc.Enabled) - { - try - { - //m_irc.Connect(m_scenes); - if (m_irc_connector == null) - { - m_irc_connector = new Thread(IRCConnectRun); - m_irc_connector.Name = "IRCConnectorThread"; - m_irc_connector.IsBackground = true; - } - if (!m_irc_connector.IsAlive) - { - m_irc_connector.Start(); - ThreadTracker.Add(m_irc_connector); - } - } - catch (Exception) - { - } - } - } - - public void Close() - { - m_irc.Close(); - } - - public string Name - { - get { return "ChatModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public void NewClient(IClientAPI client) - { - try - { - client.OnChatFromViewer += SimChat; - - if ((m_irc.Enabled) && (m_irc.Connected)) - { - string clientName = client.FirstName + " " + client.LastName; - // handles simple case. May not work for hundred connecting in per second. - // and the NewClients calles getting interleved - // but filters out multiple reports - if (clientName != m_last_new_user) - { - m_last_new_user = clientName; - string clientRegion = FindClientRegion(client.FirstName, client.LastName); - m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in "+clientRegion); - } - } - client.OnLogout += ClientLoggedOut; - client.OnConnectionClosed += ClientLoggedOut; - client.OnLogout += ClientLoggedOut; - } - catch (Exception ex) - { - m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString()); - } - } - - public void ClientLoggedOut(IClientAPI client) - { - lock (m_syncLogout) - { - try - { - if ((m_irc.Enabled) && (m_irc.Connected)) - { - string clientName = client.FirstName + " " + client.LastName; - string clientRegion = FindClientRegion(client.FirstName, client.LastName); - // handles simple case. May not work for hundred connecting in per second. - // and the NewClients calles getting interleved - // but filters out multiple reports - if (clientName != m_last_leaving_user) - { - m_last_leaving_user = clientName; - m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion); - m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion); - } - } - } - catch (Exception ex) - { - m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString()); - } - } - } - - private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos, - LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message) - { - if (!presence.IsChildAgent) - { - LLVector3 fromRegionPos = fromPos + regionPos; - LLVector3 toRegionPos = presence.AbsolutePosition + regionPos; - 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); - } - } - - public void SimChat(Object sender, ChatFromViewerArgs e) - { - // FROM: Sim TO: IRC - - ScenePresence avatar = null; - - //TODO: Move ForEachScenePresence and others into IScene. - Scene scene = (Scene) e.Scene; - - //TODO: Remove the need for this check - if (scene == null) - scene = m_scenes[0]; - - // Filled in since it's easier than rewriting right now. - LLVector3 fromPos = e.Position; - LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); - - string fromName = e.From; - string message = e.Message; - LLUUID fromAgentID = LLUUID.Zero; - - if (e.Sender != null) - { - avatar = scene.GetScenePresence(e.Sender.AgentId); - } - - if (avatar != null) - { - fromPos = avatar.AbsolutePosition; - regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); - fromName = avatar.Firstname + " " + avatar.Lastname; - fromAgentID = e.Sender.AgentId; - } - - // Try to reconnect to server if not connected - if (m_irc.Enabled && !m_irc.Connected) - { - // In a non-blocking way. Eventually the connector will get it started - try - { - if (m_irc_connector == null) - { - m_irc_connector = new Thread(IRCConnectRun); - m_irc_connector.Name = "IRCConnectorThread"; - m_irc_connector.IsBackground = true; - } - if (!m_irc_connector.IsAlive) - { - m_irc_connector.Start(); - ThreadTracker.Add(m_irc_connector); - } - } - catch (Exception) - { - } - } - - - // We only want to relay stuff on channel 0 - if (e.Channel == 0) - { - // IRC stuff - if (e.Message.Length > 0) - { - if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC - { - m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); - } - } - - foreach (Scene s in m_scenes) - { - s.ForEachScenePresence(delegate(ScenePresence presence) - { - TrySendChatMessage(presence, fromPos, regionPos, - fromAgentID, fromName, e.Type, message); - }); - } - } - } - - // if IRC is enabled then just keep trying using a monitor thread - public void IRCConnectRun() - { - while(true) - { - if ((m_irc.Enabled)&&(!m_irc.Connected)) - { - m_irc.Connect(m_scenes); - } - Thread.Sleep(15000); - } - } - - public string FindClientRegion(string client_FirstName,string client_LastName) - { - string sourceRegion = null; - foreach (Scene s in m_scenes) - { - s.ForEachScenePresence(delegate(ScenePresence presence) - { - if ((presence.IsChildAgent==false) - &&(presence.Firstname==client_FirstName) - &&(presence.Lastname==client_LastName)) - { - sourceRegion = presence.Scene.RegionInfo.RegionName; - //sourceRegion= s.RegionInfo.RegionName; - } - }); - if (sourceRegion != null) return sourceRegion; - } - if (m_defaultzone == null) { m_defaultzone = "Sim"; } - return m_defaultzone; - } - } - - internal class IRCChatModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private string m_server = null; - private uint m_port = 6668; - private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot"; - private string m_nick = null; - private string m_basenick = null; - private string m_channel = null; - private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"; - - private NetworkStream m_stream; - private TcpClient m_tcp; - private StreamWriter m_writer; - private StreamReader m_reader; - - private Thread pingSender; - private Thread listener; - internal object m_syncConnect = new object(); - - private bool m_enabled = false; - private bool m_connected = false; - - private List m_scenes = null; - private List m_last_scenes = null; - - public IRCChatModule(IConfigSource config) - { - m_nick = "OSimBot" + Util.RandomClass.Next(1, 99); - m_tcp = null; - m_writer = null; - m_reader = null; - - // configuration in OpenSim.ini - // [IRC] - // server = chat.freenode.net - // nick = OSimBot_mysim - // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot - // ; username is the IRC command line sent - // ; USER * : - // channel = #opensim-regions - // port = 6667 - // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message - // ;for : : - // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" - // ;for : - : - // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" - // ;for : - from : - // ;msgformat = "PRIVMSG {0} : {3} - from {1}" - // Traps I/O disconnects so it does not crash the sim - // Trys to reconnect if disconnected and someone says something - // Tells IRC server "QUIT" when doing a close (just to be nice) - // Default port back to 6667 - - try - { - m_server = config.Configs["IRC"].GetString("server"); - m_nick = config.Configs["IRC"].GetString("nick"); - m_basenick = m_nick; - m_channel = config.Configs["IRC"].GetString("channel"); - m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port); - m_user = config.Configs["IRC"].GetString("username", m_user); - m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat); - if (m_server != null && m_nick != null && m_channel != null) - { - m_nick = m_nick + Util.RandomClass.Next(1, 99); - m_enabled = true; - } - } - catch (Exception) - { - m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration"); - } - } - - public bool Connect(List scenes) - { - lock (m_syncConnect) - { - try - { - if (m_connected) return true; - m_scenes = scenes; - if (m_last_scenes == null) { m_last_scenes = scenes; } - - m_tcp = new TcpClient(m_server, (int)m_port); - m_log.Info("[IRC]: Connecting..."); - m_stream = m_tcp.GetStream(); - m_log.Info("[IRC]: Connected to " + m_server); - m_reader = new StreamReader(m_stream); - m_writer = new StreamWriter(m_stream); - - pingSender = new Thread(new ThreadStart(PingRun)); - pingSender.Name = "PingSenderThread"; - pingSender.IsBackground = true; - pingSender.Start(); - ThreadTracker.Add(pingSender); - - listener = new Thread(new ThreadStart(ListenerRun)); - listener.Name = "IRCChatModuleListenerThread"; - listener.IsBackground = true; - listener.Start(); - ThreadTracker.Add(listener); - - m_writer.WriteLine(m_user); - m_writer.Flush(); - m_writer.WriteLine("NICK " + m_nick); - m_writer.Flush(); - m_writer.WriteLine("JOIN " + m_channel); - m_writer.Flush(); - m_log.Info("[IRC]: Connection fully established"); - m_connected = true; - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - } - return m_connected; - } - } - - public bool Enabled - { - get { return m_enabled; } - } - - public bool Connected - { - get { return m_connected; } - } - - public string Nick - { - get { return m_nick; } - } - - public void Reconnect() - { - m_connected = false; - listener.Abort(); - pingSender.Abort(); - m_writer.Close(); - m_reader.Close(); - m_tcp.Close(); - if (m_enabled) { Connect(m_last_scenes); } - } - - public void PrivMsg(string from, string region, string msg) - { - // One message to the IRC server - - try - { - if (m_privmsgformat == null) - { - m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg); - } - else - { - m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg); - } - m_writer.Flush(); - m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg); - } - catch (IOException) - { - m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)"); - Reconnect(); - } - catch (Exception ex) - { - m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString()); - } - } - - private Dictionary ExtractMsg(string input) - { - //examines IRC commands and extracts any private messages - // which will then be reboadcast in the Sim - - m_log.Info("[IRC]: ExtractMsg: " + input); - Dictionary result = null; - //string regex = @":(?\w*)!~(?\S*) PRIVMSG (?\S+) :(?.*)"; - string regex = @":(?\w*)!(?\S*) PRIVMSG (?\S+) :(?.*)"; - Regex RE = new Regex(regex, RegexOptions.Multiline); - MatchCollection matches = RE.Matches(input); - // Get some direct matches $1 $4 is a - if ((matches.Count == 1) && (matches[0].Groups.Count == 5)) - { - 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); - } - else - { - m_log.Info("[IRC]: Number of matches: " + matches.Count); - if (matches.Count > 0) - { - m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count); - } - } - return result; - } - - public void PingRun() - { - // IRC keep alive thread - // send PING ever 15 seconds - while (true) - { - try - { - if (m_connected == true) - { - m_writer.WriteLine("PING :" + m_server); - m_writer.Flush(); - Thread.Sleep(15000); - } - } - catch (IOException) - { - m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)"); - Reconnect(); - } - catch (Exception ex) - { - m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); - } - } - } - - public void ListenerRun() - { - string inputLine; - LLVector3 pos = new LLVector3(128, 128, 20); - while (true) - { - try - { - while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null)) - { - // Console.WriteLine(inputLine); - if (inputLine.Contains(m_channel)) - { - Dictionary data = ExtractMsg(inputLine); - // Any chat ??? - if (data != null) - { - foreach (Scene m_scene in m_scenes) - { - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - if (!avatar.IsChildAgent) - { - avatar.ControllingClient.SendChatMessage( - Helpers.StringToField(data["msg"]), 255, - pos, data["nick"], - LLUUID.Zero); - } - }); - } - } - else - { - // Was an command from the IRC server - ProcessIRCCommand(inputLine); - } - } - else - { - // Was an command from the IRC server - ProcessIRCCommand(inputLine); - } - Thread.Sleep(150); - } - } - catch (IOException) - { - m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)"); - Reconnect(); - } - catch (Exception ex) - { - m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); - } - } - } - - public void BroadcastSim(string message,string sender) - { - LLVector3 pos = new LLVector3(128, 128, 20); - try - { - foreach (Scene m_scene in m_scenes) - { - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - if (!avatar.IsChildAgent) - { - avatar.ControllingClient.SendChatMessage( - Helpers.StringToField(message), 255, - pos, sender, - LLUUID.Zero); - } - }); - } - } - catch (Exception ex) // IRC gate should not crash Sim - { - m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace); - } - } - - public enum ErrorReplies - { - NotRegistered = 451, // ":You have not registered" - NicknameInUse = 433 // " :Nickname is already in use" - } - - public enum Replies - { - MotdStart = 375, // ":- Message of the day - " - Motd = 372, // ":- " - EndOfMotd = 376 // ":End of /MOTD command" - } - - public void ProcessIRCCommand(string command) - { - //m_log.Info("[IRC]: ProcessIRCCommand:" + command); - - string[] commArgs = new string[command.Split(' ').Length]; - string c_server = m_server; - - commArgs = command.Split(' '); - if (commArgs[0].Substring(0, 1) == ":") - { - commArgs[0] = commArgs[0].Remove(0, 1); - } - - if (commArgs[1] == "002") - { - // fetch the correct servername - // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/... - // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch - - c_server = (commArgs[6].Split('['))[0]; - m_server = c_server; - } - - if (commArgs[0] == "ERROR") - { - m_log.Error("[IRC]: IRC SERVER ERROR:" + command); - } - - if (commArgs[0] == "PING") - { - string p_reply = ""; - - for (int i = 1; i < commArgs.Length; i++) - { - p_reply += commArgs[i] + " "; - } - - m_writer.WriteLine("PONG " + p_reply); - m_writer.Flush(); - } - else if (commArgs[0] == c_server) - { - // server message - try - { - Int32 commandCode = Int32.Parse(commArgs[1]); - switch (commandCode) - { - case (int)ErrorReplies.NicknameInUse: - // Gen a new name - m_nick = m_basenick + Util.RandomClass.Next(1, 99); - m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick); - // Retry - m_writer.WriteLine("NICK " + m_nick); - m_writer.Flush(); - m_writer.WriteLine("JOIN " + m_channel); - m_writer.Flush(); - break; - case (int)ErrorReplies.NotRegistered: - break; - case (int)Replies.EndOfMotd: - break; - } - } - catch (Exception) - { - } - } - else - { - // Normal message - string commAct = commArgs[1]; - switch (commAct) - { - case "JOIN": eventIrcJoin(commArgs); break; - case "PART": eventIrcPart(commArgs); break; - case "MODE": eventIrcMode(commArgs); break; - case "NICK": eventIrcNickChange(commArgs); break; - case "KICK": eventIrcKick(commArgs); break; - case "QUIT": eventIrcQuit(commArgs); break; - case "PONG": break; // that's nice - } - } - } - - public void eventIrcJoin(string[] commArgs) - { - string IrcChannel = commArgs[2]; - string IrcUser = commArgs[0].Split('!')[0]; - BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick); - } - - public void eventIrcPart(string[] commArgs) - { - string IrcChannel = commArgs[2]; - string IrcUser = commArgs[0].Split('!')[0]; - BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick); - } - - public void eventIrcMode(string[] commArgs) - { - string IrcChannel = commArgs[2]; - string IrcUser = commArgs[0].Split('!')[0]; - string UserMode = ""; - for (int i = 3; i < commArgs.Length; i++) - { - UserMode += commArgs[i] + " "; - } - - if (UserMode.Substring(0, 1) == ":") - { - UserMode = UserMode.Remove(0, 1); - } - } - - public void eventIrcNickChange(string[] commArgs) - { - string UserOldNick = commArgs[0].Split('!')[0]; - string UserNewNick = commArgs[2].Remove(0, 1); - BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick); - } - - public void eventIrcKick(string[] commArgs) - { - string UserKicker = commArgs[0].Split('!')[0]; - string UserKicked = commArgs[3]; - string IrcChannel = commArgs[2]; - string KickMessage = ""; - for (int i = 4; i < commArgs.Length; i++) - { - KickMessage += commArgs[i] + " "; - } - BroadcastSim(UserKicker + " kicked " + UserKicked +" on "+IrcChannel+" saying "+KickMessage, m_nick); - if (UserKicked == m_nick) - { - BroadcastSim("Hey, that was me!!!", m_nick); - } - } - - public void eventIrcQuit(string[] commArgs) - { - string IrcUser = commArgs[0].Split('!')[0]; - string QuitMessage = ""; - - for (int i = 2; i < commArgs.Length; i++) - { - QuitMessage += commArgs[i] + " "; - } - BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick); - } - - public void Close() - { - m_connected = false; - m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing"); - m_writer.Flush(); - listener.Abort(); - pingSender.Abort(); - m_writer.Close(); - m_reader.Close(); - m_tcp.Close(); - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Avatar.Chat +{ + public class ChatModule : IRegionModule, ISimChat + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private List m_scenes = new List(); + + private int m_whisperdistance = 10; + private int m_saydistance = 30; + private int m_shoutdistance = 100; + + private IRCChatModule m_irc = null; + + private string m_last_new_user = null; + private string m_last_leaving_user = null; + private string m_defaultzone = null; + internal object m_syncInit = new object(); + internal object m_syncLogout = new object(); + private Thread m_irc_connector=null; + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_syncInit) + { + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnNewClient += NewClient; + scene.RegisterModuleInterface(this); + } + + // wrap this in a try block so that defaults will work if + // the config file doesn't specify otherwise. + 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); + } + catch (Exception) + { + } + + try + { + m_defaultzone = config.Configs["IRC"].GetString("nick","Sim"); + } + catch (Exception) + { + } + + // setup IRC Relay + if (m_irc == null) { m_irc = new IRCChatModule(config); } + if (m_irc_connector == null) + { + m_irc_connector = new Thread(IRCConnectRun); + m_irc_connector.Name = "IRCConnectorThread"; + m_irc_connector.IsBackground = true; + } + } + } + + public void PostInitialise() + { + if (m_irc.Enabled) + { + try + { + //m_irc.Connect(m_scenes); + if (m_irc_connector == null) + { + m_irc_connector = new Thread(IRCConnectRun); + m_irc_connector.Name = "IRCConnectorThread"; + m_irc_connector.IsBackground = true; + } + if (!m_irc_connector.IsAlive) + { + m_irc_connector.Start(); + ThreadTracker.Add(m_irc_connector); + } + } + catch (Exception) + { + } + } + } + + public void Close() + { + m_irc.Close(); + } + + public string Name + { + get { return "ChatModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + try + { + client.OnChatFromViewer += SimChat; + + if ((m_irc.Enabled) && (m_irc.Connected)) + { + string clientName = client.FirstName + " " + client.LastName; + // handles simple case. May not work for hundred connecting in per second. + // and the NewClients calles getting interleved + // but filters out multiple reports + if (clientName != m_last_new_user) + { + m_last_new_user = clientName; + string clientRegion = FindClientRegion(client.FirstName, client.LastName); + m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in "+clientRegion); + } + } + client.OnLogout += ClientLoggedOut; + client.OnConnectionClosed += ClientLoggedOut; + client.OnLogout += ClientLoggedOut; + } + catch (Exception ex) + { + m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString()); + } + } + + public void ClientLoggedOut(IClientAPI client) + { + lock (m_syncLogout) + { + try + { + if ((m_irc.Enabled) && (m_irc.Connected)) + { + string clientName = client.FirstName + " " + client.LastName; + string clientRegion = FindClientRegion(client.FirstName, client.LastName); + // handles simple case. May not work for hundred connecting in per second. + // and the NewClients calles getting interleved + // but filters out multiple reports + if (clientName != m_last_leaving_user) + { + m_last_leaving_user = clientName; + m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion); + m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion); + } + } + } + catch (Exception ex) + { + m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString()); + } + } + } + + private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos, + LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message) + { + if (!presence.IsChildAgent) + { + LLVector3 fromRegionPos = fromPos + regionPos; + LLVector3 toRegionPos = presence.AbsolutePosition + regionPos; + 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); + } + } + + public void SimChat(Object sender, ChatFromViewerArgs e) + { + // FROM: Sim TO: IRC + + ScenePresence avatar = null; + + //TODO: Move ForEachScenePresence and others into IScene. + Scene scene = (Scene) e.Scene; + + //TODO: Remove the need for this check + if (scene == null) + scene = m_scenes[0]; + + // Filled in since it's easier than rewriting right now. + LLVector3 fromPos = e.Position; + LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + + string fromName = e.From; + string message = e.Message; + LLUUID fromAgentID = LLUUID.Zero; + + if (e.Sender != null) + { + avatar = scene.GetScenePresence(e.Sender.AgentId); + } + + if (avatar != null) + { + fromPos = avatar.AbsolutePosition; + regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + fromName = avatar.Firstname + " " + avatar.Lastname; + fromAgentID = e.Sender.AgentId; + } + + // Try to reconnect to server if not connected + if (m_irc.Enabled && !m_irc.Connected) + { + // In a non-blocking way. Eventually the connector will get it started + try + { + if (m_irc_connector == null) + { + m_irc_connector = new Thread(IRCConnectRun); + m_irc_connector.Name = "IRCConnectorThread"; + m_irc_connector.IsBackground = true; + } + if (!m_irc_connector.IsAlive) + { + m_irc_connector.Start(); + ThreadTracker.Add(m_irc_connector); + } + } + catch (Exception) + { + } + } + + + // We only want to relay stuff on channel 0 + if (e.Channel == 0) + { + // IRC stuff + if (e.Message.Length > 0) + { + if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC + { + m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); + } + } + + foreach (Scene s in m_scenes) + { + s.ForEachScenePresence(delegate(ScenePresence presence) + { + TrySendChatMessage(presence, fromPos, regionPos, + fromAgentID, fromName, e.Type, message); + }); + } + } + } + + // if IRC is enabled then just keep trying using a monitor thread + public void IRCConnectRun() + { + while(true) + { + if ((m_irc.Enabled)&&(!m_irc.Connected)) + { + m_irc.Connect(m_scenes); + } + Thread.Sleep(15000); + } + } + + public string FindClientRegion(string client_FirstName,string client_LastName) + { + string sourceRegion = null; + foreach (Scene s in m_scenes) + { + s.ForEachScenePresence(delegate(ScenePresence presence) + { + if ((presence.IsChildAgent==false) + &&(presence.Firstname==client_FirstName) + &&(presence.Lastname==client_LastName)) + { + sourceRegion = presence.Scene.RegionInfo.RegionName; + //sourceRegion= s.RegionInfo.RegionName; + } + }); + if (sourceRegion != null) return sourceRegion; + } + if (m_defaultzone == null) { m_defaultzone = "Sim"; } + return m_defaultzone; + } + } + + internal class IRCChatModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_server = null; + private uint m_port = 6668; + private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot"; + private string m_nick = null; + private string m_basenick = null; + private string m_channel = null; + private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"; + + private NetworkStream m_stream; + private TcpClient m_tcp; + private StreamWriter m_writer; + private StreamReader m_reader; + + private Thread pingSender; + private Thread listener; + internal object m_syncConnect = new object(); + + private bool m_enabled = false; + private bool m_connected = false; + + private List m_scenes = null; + private List m_last_scenes = null; + + public IRCChatModule(IConfigSource config) + { + m_nick = "OSimBot" + Util.RandomClass.Next(1, 99); + m_tcp = null; + m_writer = null; + m_reader = null; + + // configuration in OpenSim.ini + // [IRC] + // server = chat.freenode.net + // nick = OSimBot_mysim + // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot + // ; username is the IRC command line sent + // ; USER * : + // channel = #opensim-regions + // port = 6667 + // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message + // ;for : : + // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" + // ;for : - : + // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" + // ;for : - from : + // ;msgformat = "PRIVMSG {0} : {3} - from {1}" + // Traps I/O disconnects so it does not crash the sim + // Trys to reconnect if disconnected and someone says something + // Tells IRC server "QUIT" when doing a close (just to be nice) + // Default port back to 6667 + + try + { + m_server = config.Configs["IRC"].GetString("server"); + m_nick = config.Configs["IRC"].GetString("nick"); + m_basenick = m_nick; + m_channel = config.Configs["IRC"].GetString("channel"); + m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port); + m_user = config.Configs["IRC"].GetString("username", m_user); + m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat); + if (m_server != null && m_nick != null && m_channel != null) + { + m_nick = m_nick + Util.RandomClass.Next(1, 99); + m_enabled = true; + } + } + catch (Exception) + { + m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration"); + } + } + + public bool Connect(List scenes) + { + lock (m_syncConnect) + { + try + { + if (m_connected) return true; + m_scenes = scenes; + if (m_last_scenes == null) { m_last_scenes = scenes; } + + m_tcp = new TcpClient(m_server, (int)m_port); + m_log.Info("[IRC]: Connecting..."); + m_stream = m_tcp.GetStream(); + m_log.Info("[IRC]: Connected to " + m_server); + m_reader = new StreamReader(m_stream); + m_writer = new StreamWriter(m_stream); + + pingSender = new Thread(new ThreadStart(PingRun)); + pingSender.Name = "PingSenderThread"; + pingSender.IsBackground = true; + pingSender.Start(); + ThreadTracker.Add(pingSender); + + listener = new Thread(new ThreadStart(ListenerRun)); + listener.Name = "IRCChatModuleListenerThread"; + listener.IsBackground = true; + listener.Start(); + ThreadTracker.Add(listener); + + m_writer.WriteLine(m_user); + m_writer.Flush(); + m_writer.WriteLine("NICK " + m_nick); + m_writer.Flush(); + m_writer.WriteLine("JOIN " + m_channel); + m_writer.Flush(); + m_log.Info("[IRC]: Connection fully established"); + m_connected = true; + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + return m_connected; + } + } + + public bool Enabled + { + get { return m_enabled; } + } + + public bool Connected + { + get { return m_connected; } + } + + public string Nick + { + get { return m_nick; } + } + + public void Reconnect() + { + m_connected = false; + listener.Abort(); + pingSender.Abort(); + m_writer.Close(); + m_reader.Close(); + m_tcp.Close(); + if (m_enabled) { Connect(m_last_scenes); } + } + + public void PrivMsg(string from, string region, string msg) + { + // One message to the IRC server + + try + { + if (m_privmsgformat == null) + { + m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg); + } + else + { + m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg); + } + m_writer.Flush(); + m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg); + } + catch (IOException) + { + m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)"); + Reconnect(); + } + catch (Exception ex) + { + m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString()); + } + } + + private Dictionary ExtractMsg(string input) + { + //examines IRC commands and extracts any private messages + // which will then be reboadcast in the Sim + + m_log.Info("[IRC]: ExtractMsg: " + input); + Dictionary result = null; + //string regex = @":(?\w*)!~(?\S*) PRIVMSG (?\S+) :(?.*)"; + string regex = @":(?\w*)!(?\S*) PRIVMSG (?\S+) :(?.*)"; + Regex RE = new Regex(regex, RegexOptions.Multiline); + MatchCollection matches = RE.Matches(input); + // Get some direct matches $1 $4 is a + if ((matches.Count == 1) && (matches[0].Groups.Count == 5)) + { + 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); + } + else + { + m_log.Info("[IRC]: Number of matches: " + matches.Count); + if (matches.Count > 0) + { + m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count); + } + } + return result; + } + + public void PingRun() + { + // IRC keep alive thread + // send PING ever 15 seconds + while (true) + { + try + { + if (m_connected == true) + { + m_writer.WriteLine("PING :" + m_server); + m_writer.Flush(); + Thread.Sleep(15000); + } + } + catch (IOException) + { + m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)"); + Reconnect(); + } + catch (Exception ex) + { + m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); + } + } + } + + public void ListenerRun() + { + string inputLine; + LLVector3 pos = new LLVector3(128, 128, 20); + while (true) + { + try + { + while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null)) + { + // Console.WriteLine(inputLine); + if (inputLine.Contains(m_channel)) + { + Dictionary data = ExtractMsg(inputLine); + // Any chat ??? + if (data != null) + { + foreach (Scene m_scene in m_scenes) + { + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + if (!avatar.IsChildAgent) + { + avatar.ControllingClient.SendChatMessage( + Helpers.StringToField(data["msg"]), 255, + pos, data["nick"], + LLUUID.Zero); + } + }); + } + } + else + { + // Was an command from the IRC server + ProcessIRCCommand(inputLine); + } + } + else + { + // Was an command from the IRC server + ProcessIRCCommand(inputLine); + } + Thread.Sleep(150); + } + } + catch (IOException) + { + m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)"); + Reconnect(); + } + catch (Exception ex) + { + m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); + } + } + } + + public void BroadcastSim(string message,string sender) + { + LLVector3 pos = new LLVector3(128, 128, 20); + try + { + foreach (Scene m_scene in m_scenes) + { + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + if (!avatar.IsChildAgent) + { + avatar.ControllingClient.SendChatMessage( + Helpers.StringToField(message), 255, + pos, sender, + LLUUID.Zero); + } + }); + } + } + catch (Exception ex) // IRC gate should not crash Sim + { + m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace); + } + } + + public enum ErrorReplies + { + NotRegistered = 451, // ":You have not registered" + NicknameInUse = 433 // " :Nickname is already in use" + } + + public enum Replies + { + MotdStart = 375, // ":- Message of the day - " + Motd = 372, // ":- " + EndOfMotd = 376 // ":End of /MOTD command" + } + + public void ProcessIRCCommand(string command) + { + //m_log.Info("[IRC]: ProcessIRCCommand:" + command); + + string[] commArgs = new string[command.Split(' ').Length]; + string c_server = m_server; + + commArgs = command.Split(' '); + if (commArgs[0].Substring(0, 1) == ":") + { + commArgs[0] = commArgs[0].Remove(0, 1); + } + + if (commArgs[1] == "002") + { + // fetch the correct servername + // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/... + // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch + + c_server = (commArgs[6].Split('['))[0]; + m_server = c_server; + } + + if (commArgs[0] == "ERROR") + { + m_log.Error("[IRC]: IRC SERVER ERROR:" + command); + } + + if (commArgs[0] == "PING") + { + string p_reply = ""; + + for (int i = 1; i < commArgs.Length; i++) + { + p_reply += commArgs[i] + " "; + } + + m_writer.WriteLine("PONG " + p_reply); + m_writer.Flush(); + } + else if (commArgs[0] == c_server) + { + // server message + try + { + Int32 commandCode = Int32.Parse(commArgs[1]); + switch (commandCode) + { + case (int)ErrorReplies.NicknameInUse: + // Gen a new name + m_nick = m_basenick + Util.RandomClass.Next(1, 99); + m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick); + // Retry + m_writer.WriteLine("NICK " + m_nick); + m_writer.Flush(); + m_writer.WriteLine("JOIN " + m_channel); + m_writer.Flush(); + break; + case (int)ErrorReplies.NotRegistered: + break; + case (int)Replies.EndOfMotd: + break; + } + } + catch (Exception) + { + } + } + else + { + // Normal message + string commAct = commArgs[1]; + switch (commAct) + { + case "JOIN": eventIrcJoin(commArgs); break; + case "PART": eventIrcPart(commArgs); break; + case "MODE": eventIrcMode(commArgs); break; + case "NICK": eventIrcNickChange(commArgs); break; + case "KICK": eventIrcKick(commArgs); break; + case "QUIT": eventIrcQuit(commArgs); break; + case "PONG": break; // that's nice + } + } + } + + public void eventIrcJoin(string[] commArgs) + { + string IrcChannel = commArgs[2]; + string IrcUser = commArgs[0].Split('!')[0]; + BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick); + } + + public void eventIrcPart(string[] commArgs) + { + string IrcChannel = commArgs[2]; + string IrcUser = commArgs[0].Split('!')[0]; + BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick); + } + + public void eventIrcMode(string[] commArgs) + { + string IrcChannel = commArgs[2]; + string IrcUser = commArgs[0].Split('!')[0]; + string UserMode = ""; + for (int i = 3; i < commArgs.Length; i++) + { + UserMode += commArgs[i] + " "; + } + + if (UserMode.Substring(0, 1) == ":") + { + UserMode = UserMode.Remove(0, 1); + } + } + + public void eventIrcNickChange(string[] commArgs) + { + string UserOldNick = commArgs[0].Split('!')[0]; + string UserNewNick = commArgs[2].Remove(0, 1); + BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick); + } + + public void eventIrcKick(string[] commArgs) + { + string UserKicker = commArgs[0].Split('!')[0]; + string UserKicked = commArgs[3]; + string IrcChannel = commArgs[2]; + string KickMessage = ""; + for (int i = 4; i < commArgs.Length; i++) + { + KickMessage += commArgs[i] + " "; + } + BroadcastSim(UserKicker + " kicked " + UserKicked +" on "+IrcChannel+" saying "+KickMessage, m_nick); + if (UserKicked == m_nick) + { + BroadcastSim("Hey, that was me!!!", m_nick); + } + } + + public void eventIrcQuit(string[] commArgs) + { + string IrcUser = commArgs[0].Split('!')[0]; + string QuitMessage = ""; + + for (int i = 2; i < commArgs.Length; i++) + { + QuitMessage += commArgs[i] + " "; + } + BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick); + } + + public void Close() + { + m_connected = false; + m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing"); + m_writer.Flush(); + listener.Abort(); + pingSender.Abort(); + m_writer.Close(); + m_reader.Close(); + m_tcp.Close(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs similarity index 93% rename from OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs index 3a8906e6e1..0e058ec087 100644 --- a/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Currency/SampleMoney/SampleMoneyModule.cs @@ -1,1490 +1,1491 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - /// - /// 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 delegate void ObjectPaid(LLUUID objectID, LLUUID agentID, int amount); - - public interface IMoneyModule : IRegionModule - { - bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount); - - event ObjectPaid OnObjectPaid; - } - - public class BetaGridLikeMoneyModule: IMoneyModule - { - public event ObjectPaid OnObjectPaid; - - private ObjectPaid handerOnObjectPaid; - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Region UUIDS indexed by AgentID - /// - Dictionary m_rootAgents = new Dictionary(); - - /// - /// Scenes by Region Handle - /// - private Dictionary m_scenel = new Dictionary(); - - private IConfigSource m_gConfig; - - private bool m_keepMoneyAcrossLogins = true; - - private int m_minFundsBeforeRefresh = 100; - - private int m_stipend = 1000; - - private bool m_enabled = true; - - private Dictionary m_KnownClientFunds = new Dictionary(); - - private bool gridmode = false; - private Scene XMLRPCHandler; - private float EnergyEfficiency = 0f; - 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 int UserLevelPaysFees = 2; - private string m_MoneyAddress = String.Empty; - private string m_LandAddress = String.Empty; - - float TeleportPriceExponent = 0f; - - /// - /// Where Stipends come from and Fees go to. - /// - LLUUID EconomyBaseAccount = LLUUID.Zero; - - /// - /// Startup - /// - /// - /// - public void Initialise(Scene scene, IConfigSource config) - { - m_gConfig = config; - - IConfig startupConfig = m_gConfig.Configs["Startup"]; - IConfig economyConfig = m_gConfig.Configs["Economy"]; - - scene.RegisterModuleInterface(this); - - ReadConfigAndPopulate(scene, startupConfig, "Startup"); - ReadConfigAndPopulate(scene, economyConfig, "Economy"); - - if (m_enabled) - { - 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 - scene.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate); - scene.AddXmlRPCHandler("userAlert", UserAlert); - } - else - { - // Local Server.. enables functionality only. - scene.AddXmlRPCHandler("getCurrencyQuote", quote_func); - scene.AddXmlRPCHandler("buyCurrency", buy_func); - scene.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func); - scene.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; - - } - } - /// - /// 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", LLUUID.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); - } - - /// - /// New Client Event Handler - /// - /// - private void OnNewClient(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; - LLUUID agentID = LLUUID.Zero; - int funds = 0; - - Hashtable hbinfo = GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID.ToString(), s.RegionInfo.regionSecret); - if ((bool)hbinfo["success"] == true) - { - - Helpers.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, LLUUID.Zero); - - } - } - - } - else - { - CheckExistAndRefreshFunds(client.AgentId); - } - - // Subscribe to Money messages - client.OnEconomyDataRequest += EconomyDataRequestHandler; - client.OnMoneyBalanceRequest += SendMoneyBalance; - client.OnRequestPayPrice += requestPayPrice; - client.OnLogout += ClientClosed; - - - } - - #region event Handlers - - public void requestPayPrice(IClientAPI client, LLUUID 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(LLUUID 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(LLUUID 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(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); - } - if(receiver != null) - { - receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(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(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); - } - } - - if (receiver != null) - { - receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(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.Info("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); - } - - } - } - - } - - /// - /// Event Handler for when the client logs out. - /// - /// - private void ClientLoggedOut(LLUUID 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, LLUUID 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 - { - 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()); - } - - #endregion - - /// - /// Transfer money - /// - /// - /// - /// - /// - private bool doMoneyTransfer(LLUUID Sender, LLUUID 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; - } - - #region Utility Helpers - /// - /// Locates a IClientAPI for the client specified - /// - /// - /// - private IClientAPI LocateClientObject(LLUUID 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(LLUUID 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(LLUUID RegionID) - { - lock (m_scenel) - { - foreach (Scene rs in m_scenel.Values) - { - if (rs.RegionInfo.originRegionID == RegionID) - { - return rs; - } - } - } - return null; - } - #endregion - - - - /// - /// Sends the the stored money balance to the client - /// - /// - /// - /// - /// - public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID 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!"); - } - } - - #region local Fund Management - /// - /// Ensures that the agent accounting data is set up in this instance. - /// - /// - private void CheckExistAndRefreshFunds(LLUUID 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(LLUUID 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(LLUUID AgentID, int amount) - { - lock (m_KnownClientFunds) - { - if (m_KnownClientFunds.ContainsKey(AgentID)) - { - m_KnownClientFunds[AgentID] = amount; - } - else - { - m_KnownClientFunds.Add(AgentID, amount); - } - } - - } - - #endregion - - /// - /// Gets the current balance for the user from the Grid Money Server - /// - /// - /// - /// - /// - /// - public Hashtable GetBalanceForUserFromMoneyServer(LLUUID agentId, LLUUID secureSessionID, LLUUID 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(LLUUID agentId, LLUUID secureSessionID, LLUUID 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, LLUUID.Zero); - } - return MoneyRespData; - } - - private SceneObjectPart findPrim(LLUUID 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(LLUUID objectID) - { - SceneObjectPart part=findPrim(objectID); - if(part != null) - { - return part.Name; - } - return String.Empty; - } - - private string resolveAgentName(LLUUID agentID) - { - // try avatar username surname - Scene scene=GetRandomScene(); - UserProfileData profile = scene.CommsManager.UserService.GetUserProfile(agentID); - if (profile != null) - { - string avatarname = profile.FirstName + " " + profile.SurName; - return avatarname; - } - return String.Empty; - } - - public bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID 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; - - - } - private void BalanceUpdate(LLUUID senderID, LLUUID receiverID, bool transactionresult, string description) - { - IClientAPI sender = LocateClientObject(senderID); - IClientAPI receiver = LocateClientObject(receiverID); - - if (senderID != receiverID) - { - if (sender != null) - { - sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(senderID)); - } - - if (receiver != null) - { - receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(receiverID)); - } - } - } - - /// - /// Informs the Money Grid Server of a transfer. - /// - /// - /// - /// - /// - public bool TransferMoneyonMoneyServer(LLUUID sourceId, LLUUID 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(LLUUID 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.ToString(), 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, LLUUID.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")) - { - LLUUID agentId = LLUUID.Zero; - - Helpers.TryParse((string)requestData["agentId"], out agentId); - if (agentId != LLUUID.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]; - - LLUUID agentId = LLUUID.Zero; - LLUUID soundId = LLUUID.Zero; - - Helpers.TryParse((string)requestData["agentId"], out agentId); - Helpers.TryParse((string)requestData["soundId"], out soundId); - string text=(string)requestData["text"]; - string secret=(string)requestData["secret"]; - - Scene userScene = GetRandomScene(); - if(userScene.RegionInfo.regionSecret.ToString() == secret) - { - IClientAPI client = LocateClientObject(agentId); - - if (client != null) - { - if(soundId != LLUUID.Zero) - client.SendPlayAttachedSound(soundId, LLUUID.Zero, LLUUID.Zero, 1.0f, 0); - client.SendBlueBoxMessage(LLUUID.Zero, LLUUID.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]; - LLUUID agentId = LLUUID.Zero; - int amount = 0; - Hashtable quoteResponse = new Hashtable(); - XmlRpcResponse returnval = new XmlRpcResponse(); - - if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) - { - Helpers.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]; - LLUUID agentId = LLUUID.Zero; - int amount = 0; - if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) - { - Helpers.TryParse((string)requestData["agentId"], out agentId); - try - { - amount = (Int32)requestData["currencyBuy"]; - } - catch (InvalidCastException) - { - - } - if (agentId != LLUUID.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, LLUUID.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]; - - LLUUID agentId = LLUUID.Zero; - int amount = 0; - if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) - { - Helpers.TryParse((string)requestData["agentId"], out agentId); - try - { - amount = (Int32)requestData["currencyBuy"]; - } - catch (InvalidCastException) - { - - } - if (agentId != LLUUID.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, LLUUID.Zero); - } - } - } - retparam.Add("success", true); - ret.Value = retparam; - - return ret; - - } -#endregion - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "BetaGridLikeMoneyModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - } - public enum TransactionType : int - { - SystemGenerated=0, - RegionMoneyRequest=1, - Gift=2, - Purchase=3 - - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.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 delegate void ObjectPaid(LLUUID objectID, LLUUID agentID, int amount); + + public interface IMoneyModule : IRegionModule + { + bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID toID, int amount); + + event ObjectPaid OnObjectPaid; + } + + public class SampleMoneyModule : IMoneyModule + { + public event ObjectPaid OnObjectPaid; + + private ObjectPaid handerOnObjectPaid; + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Region UUIDS indexed by AgentID + /// + Dictionary m_rootAgents = new Dictionary(); + + /// + /// Scenes by Region Handle + /// + private Dictionary m_scenel = new Dictionary(); + + private IConfigSource m_gConfig; + + private bool m_keepMoneyAcrossLogins = true; + + private int m_minFundsBeforeRefresh = 100; + + private int m_stipend = 1000; + + private bool m_enabled = true; + + private Dictionary m_KnownClientFunds = new Dictionary(); + + private bool gridmode = false; + private Scene XMLRPCHandler; + private float EnergyEfficiency = 0f; + 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 int UserLevelPaysFees = 2; + private string m_MoneyAddress = String.Empty; + private string m_LandAddress = String.Empty; + + float TeleportPriceExponent = 0f; + + /// + /// Where Stipends come from and Fees go to. + /// + LLUUID EconomyBaseAccount = LLUUID.Zero; + + /// + /// Startup + /// + /// + /// + public void Initialise(Scene scene, IConfigSource config) + { + m_gConfig = config; + + IConfig startupConfig = m_gConfig.Configs["Startup"]; + IConfig economyConfig = m_gConfig.Configs["Economy"]; + + scene.RegisterModuleInterface(this); + + ReadConfigAndPopulate(scene, startupConfig, "Startup"); + ReadConfigAndPopulate(scene, economyConfig, "Economy"); + + if (m_enabled) + { + 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 + scene.AddXmlRPCHandler("balanceUpdateRequest", GridMoneyUpdate); + scene.AddXmlRPCHandler("userAlert", UserAlert); + } + else + { + // Local Server.. enables functionality only. + scene.AddXmlRPCHandler("getCurrencyQuote", quote_func); + scene.AddXmlRPCHandler("buyCurrency", buy_func); + scene.AddXmlRPCHandler("preflightBuyLandPrep", preflightBuyLandPrep_func); + scene.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; + + } + } + /// + /// 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", LLUUID.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); + } + + /// + /// New Client Event Handler + /// + /// + private void OnNewClient(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; + LLUUID agentID = LLUUID.Zero; + int funds = 0; + + Hashtable hbinfo = GetBalanceForUserFromMoneyServer(client.AgentId, client.SecureSessionId, s.RegionInfo.originRegionID.ToString(), s.RegionInfo.regionSecret); + if ((bool)hbinfo["success"] == true) + { + + Helpers.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, LLUUID.Zero); + + } + } + + } + else + { + CheckExistAndRefreshFunds(client.AgentId); + } + + // Subscribe to Money messages + client.OnEconomyDataRequest += EconomyDataRequestHandler; + client.OnMoneyBalanceRequest += SendMoneyBalance; + client.OnRequestPayPrice += requestPayPrice; + client.OnLogout += ClientClosed; + + + } + + #region event Handlers + + public void requestPayPrice(IClientAPI client, LLUUID 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(LLUUID 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(LLUUID 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(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); + } + if(receiver != null) + { + receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(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(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); + } + } + + if (receiver != null) + { + receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(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.Info("[MONEY]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); + } + + } + } + + } + + /// + /// Event Handler for when the client logs out. + /// + /// + private void ClientLoggedOut(LLUUID 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, LLUUID 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 + { + 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()); + } + + #endregion + + /// + /// Transfer money + /// + /// + /// + /// + /// + private bool doMoneyTransfer(LLUUID Sender, LLUUID 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; + } + + #region Utility Helpers + /// + /// Locates a IClientAPI for the client specified + /// + /// + /// + private IClientAPI LocateClientObject(LLUUID 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(LLUUID 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(LLUUID RegionID) + { + lock (m_scenel) + { + foreach (Scene rs in m_scenel.Values) + { + if (rs.RegionInfo.originRegionID == RegionID) + { + return rs; + } + } + } + return null; + } + #endregion + + + + /// + /// Sends the the stored money balance to the client + /// + /// + /// + /// + /// + public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID 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!"); + } + } + + #region local Fund Management + /// + /// Ensures that the agent accounting data is set up in this instance. + /// + /// + private void CheckExistAndRefreshFunds(LLUUID 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(LLUUID 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(LLUUID AgentID, int amount) + { + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(AgentID)) + { + m_KnownClientFunds[AgentID] = amount; + } + else + { + m_KnownClientFunds.Add(AgentID, amount); + } + } + + } + + #endregion + + /// + /// Gets the current balance for the user from the Grid Money Server + /// + /// + /// + /// + /// + /// + public Hashtable GetBalanceForUserFromMoneyServer(LLUUID agentId, LLUUID secureSessionID, LLUUID 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(LLUUID agentId, LLUUID secureSessionID, LLUUID 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, LLUUID.Zero); + } + return MoneyRespData; + } + + private SceneObjectPart findPrim(LLUUID 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(LLUUID objectID) + { + SceneObjectPart part=findPrim(objectID); + if(part != null) + { + return part.Name; + } + return String.Empty; + } + + private string resolveAgentName(LLUUID agentID) + { + // try avatar username surname + Scene scene=GetRandomScene(); + UserProfileData profile = scene.CommsManager.UserService.GetUserProfile(agentID); + if (profile != null) + { + string avatarname = profile.FirstName + " " + profile.SurName; + return avatarname; + } + return String.Empty; + } + + public bool ObjectGiveMoney(LLUUID objectID, LLUUID fromID, LLUUID 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; + + + } + private void BalanceUpdate(LLUUID senderID, LLUUID receiverID, bool transactionresult, string description) + { + IClientAPI sender = LocateClientObject(senderID); + IClientAPI receiver = LocateClientObject(receiverID); + + if (senderID != receiverID) + { + if (sender != null) + { + sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(senderID)); + } + + if (receiver != null) + { + receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(description), GetFundsForAgentID(receiverID)); + } + } + } + + /// + /// Informs the Money Grid Server of a transfer. + /// + /// + /// + /// + /// + public bool TransferMoneyonMoneyServer(LLUUID sourceId, LLUUID 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(LLUUID 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.ToString(), 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, LLUUID.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")) + { + LLUUID agentId = LLUUID.Zero; + + Helpers.TryParse((string)requestData["agentId"], out agentId); + if (agentId != LLUUID.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]; + + LLUUID agentId = LLUUID.Zero; + LLUUID soundId = LLUUID.Zero; + + Helpers.TryParse((string)requestData["agentId"], out agentId); + Helpers.TryParse((string)requestData["soundId"], out soundId); + string text=(string)requestData["text"]; + string secret=(string)requestData["secret"]; + + Scene userScene = GetRandomScene(); + if(userScene.RegionInfo.regionSecret.ToString() == secret) + { + IClientAPI client = LocateClientObject(agentId); + + if (client != null) + { + if(soundId != LLUUID.Zero) + client.SendPlayAttachedSound(soundId, LLUUID.Zero, LLUUID.Zero, 1.0f, 0); + client.SendBlueBoxMessage(LLUUID.Zero, LLUUID.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]; + LLUUID agentId = LLUUID.Zero; + int amount = 0; + Hashtable quoteResponse = new Hashtable(); + XmlRpcResponse returnval = new XmlRpcResponse(); + + if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) + { + Helpers.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]; + LLUUID agentId = LLUUID.Zero; + int amount = 0; + if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) + { + Helpers.TryParse((string)requestData["agentId"], out agentId); + try + { + amount = (Int32)requestData["currencyBuy"]; + } + catch (InvalidCastException) + { + + } + if (agentId != LLUUID.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, LLUUID.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]; + + LLUUID agentId = LLUUID.Zero; + int amount = 0; + if (requestData.ContainsKey("agentId") && requestData.ContainsKey("currencyBuy")) + { + Helpers.TryParse((string)requestData["agentId"], out agentId); + try + { + amount = (Int32)requestData["currencyBuy"]; + } + catch (InvalidCastException) + { + + } + if (agentId != LLUUID.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, LLUUID.Zero); + } + } + } + retparam.Add("success", true); + ret.Value = retparam; + + return ret; + + } + #endregion + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "BetaGridLikeMoneyModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } + + public enum TransactionType : int + { + SystemGenerated=0, + RegionMoneyRequest=1, + Gift=2, + Purchase=3 + + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs similarity index 94% rename from OpenSim/Region/Environment/Modules/FriendsModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs index 707890683b..3b0cc4cc6e 100644 --- a/OpenSim/Region/Environment/Modules/FriendsModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs @@ -1,504 +1,504 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using libsecondlife.Packets; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class FriendsModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private List m_scene = new List(); - - Dictionary m_rootAgents = new Dictionary(); - - Dictionary m_pendingFriendRequests = new Dictionary(); - - Dictionary> FriendLists = new Dictionary>(); - - public void Initialise(Scene scene, IConfigSource config) - { - lock (m_scene) - { - if (m_scene.Count == 0) - { - scene.AddXmlRPCHandler("presence_update", processPresenceUpdate); - } - - if (!m_scene.Contains(scene)) - m_scene.Add(scene); - } - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage; - scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; - scene.EventManager.OnClientClosed += ClientLoggedOut; - } - public XmlRpcResponse processPresenceUpdate(XmlRpcRequest req) - { - m_log.Info("[FRIENDS]: Got Notification about a user! OMG"); - return new XmlRpcResponse(); - } - 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 - // - // The base set of friends are added when the user signs on in their XMLRPC response - // Generated by LoginService. The friends are retreived from the database by the UserManager - - // Subscribe to instant messages - - client.OnInstantMessage += OnInstantMessage; - client.OnApproveFriendRequest += OnApprovedFriendRequest; - client.OnDenyFriendRequest += OnDenyFriendRequest; - client.OnTerminateFriendship += OnTerminateFriendship; - - List fl = new List(); - - //bool addFLback = false; - - lock (FriendLists) - { - if (FriendLists.ContainsKey(client.AgentId)) - { - fl = FriendLists[client.AgentId]; - } - else - { - fl = m_scene[0].GetFriendList(client.AgentId); - - //lock (FriendLists) - //{ - if (!FriendLists.ContainsKey(client.AgentId)) - FriendLists.Add(client.AgentId, fl); - //} - } - } - - List UpdateUsers = new List(); - - foreach (FriendListItem f in fl) - { - if (m_rootAgents.ContainsKey(f.Friend)) - { - if (f.onlinestatus == false) - { - UpdateUsers.Add(f.Friend); - f.onlinestatus = true; - } - } - } - foreach (LLUUID user in UpdateUsers) - { - ScenePresence av = GetPresenceFromAgentID(user); - if (av != null) - { - List usrfl = new List(); - - lock (FriendLists) - { - usrfl = FriendLists[user]; - } - - lock (usrfl) - { - foreach (FriendListItem fli in usrfl) - { - if (fli.Friend == client.AgentId) - { - fli.onlinestatus = true; - OnlineNotificationPacket onp = new OnlineNotificationPacket(); - OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[1]; - OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = client.AgentId; - onpb[0] = onpbl; - onp.AgentBlock = onpb; - av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task); - } - } - } - } - } - - if (UpdateUsers.Count > 0) - { - OnlineNotificationPacket onp = new OnlineNotificationPacket(); - OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[UpdateUsers.Count]; - for (int i = 0; i < UpdateUsers.Count; i++) - { - OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = UpdateUsers[i]; - onpb[i] = onpbl; - } - onp.AgentBlock = onpb; - client.OutPacket(onp, ThrottleOutPacketType.Task); - } - - - - - } - - private void ClientLoggedOut(LLUUID AgentId) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(AgentId)) - { - m_rootAgents.Remove(AgentId); - m_log.Info("[FRIEND]: Removing " + AgentId + ". Agent logged out."); - } - } - List lfli = new List(); - lock (FriendLists) - { - if (FriendLists.ContainsKey(AgentId)) - { - lfli = FriendLists[AgentId]; - } - } - List updateUsers = new List(); - foreach (FriendListItem fli in lfli) - { - if (fli.onlinestatus == true) - { - updateUsers.Add(fli.Friend); - } - } - lock (updateUsers) - { - for (int i = 0; i < updateUsers.Count; i++) - { - List flfli = new List(); - try - { - - lock (FriendLists) - { - if (FriendLists.ContainsKey(updateUsers[i])) - flfli = FriendLists[updateUsers[i]]; - } - } - catch (IndexOutOfRangeException) - { - // Ignore the index out of range exception. - // This causes friend lists to get out of sync slightly.. however - // prevents a sim crash. - m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off"); - } - - for (int j = 0; j < flfli.Count; j++) - { - try - { - if (flfli[i].Friend == AgentId) - { - flfli[i].onlinestatus = false; - } - - } - - catch (IndexOutOfRangeException) - { - // Ignore the index out of range exception. - // This causes friend lists to get out of sync slightly.. however - // prevents a sim crash. - m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off"); - } - } - - } - - for (int i = 0; i < updateUsers.Count; i++) - { - ScenePresence av = GetPresenceFromAgentID(updateUsers[i]); - if (av != null) - { - - OfflineNotificationPacket onp = new OfflineNotificationPacket(); - OfflineNotificationPacket.AgentBlockBlock[] onpb = new OfflineNotificationPacket.AgentBlockBlock[1]; - OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); - onpbl.AgentID = AgentId; - onpb[0] = onpbl; - onp.AgentBlock = onpb; - av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task); - } - } - } - lock (FriendLists) - { - FriendLists.Remove(AgentId); - } - - } - - private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) - { - lock (m_rootAgents) - { - if (m_rootAgents.ContainsKey(avatar.UUID)) - { - if (avatar.RegionHandle != m_rootAgents[avatar.UUID]) - { - m_rootAgents[avatar.UUID] = avatar.RegionHandle; - m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); - if (avatar.JID.Length > 0) - { - JId avatarID = new JId(avatar.JID); - // REST Post XMPP Stanzas! - - } - // Claim User! my user! Mine mine mine! - } - } - else - { - m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); - m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); - } - } - //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); - m_log.Info("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); - } - - } - } - - } - #region FriendRequestHandling - private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID, - LLUUID fromAgentSession, LLUUID toAgentID, - LLUUID imSessionID, uint timestamp, string fromAgentName, - string message, byte dialog, bool fromGroup, byte offline, - uint ParentEstateID, LLVector3 Position, LLUUID RegionID, - byte[] binaryBucket) - { - // Friend Requests go by Instant Message.. using the dialog param - // https://wiki.secondlife.com/wiki/ImprovedInstantMessage - - // 38 == Offer friendship - if (dialog == (byte)38) - { - LLUUID friendTransactionID = LLUUID.Random(); - - m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); - - m_log.Info("[FRIEND]: 38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); - GridInstantMessage msg = new GridInstantMessage(); - msg.fromAgentID = fromAgentID.UUID; - msg.fromAgentSession = fromAgentSession.UUID; - msg.toAgentID = toAgentID.UUID; - msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here - m_log.Info("[FRIEND]: Filling Session: " + msg.imSessionID.ToString()); - msg.timestamp = timestamp; - if (client != null) - { - msg.fromAgentName = client.FirstName + " " + client.LastName;// fromAgentName; - } - else - { - msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it - } - msg.message = message; - msg.dialog = dialog; - msg.fromGroup = fromGroup; - msg.offline = offline; - msg.ParentEstateID = ParentEstateID; - msg.Position = new sLLVector3(Position); - msg.RegionID = RegionID.UUID; - msg.binaryBucket = binaryBucket; - // We don't really care which scene we pipe it through. - m_scene[0].TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); - } - - // 39 == Accept Friendship - if (dialog == (byte)39) - { - m_log.Info("[FRIEND]: 39 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); - } - - // 40 == Decline Friendship - if (dialog == (byte)40) - { - m_log.Info("[FRIEND]: 40 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); - } - } - - private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders) - { - if (m_pendingFriendRequests.ContainsKey(transactionID)) - { - // Found Pending Friend Request with that Transaction.. - Scene SceneAgentIn = m_scene[0]; - - // Found Pending Friend Request with that Transaction.. - ScenePresence agentpresence = GetPresenceFromAgentID(agentID); - if (agentpresence != null) - { - SceneAgentIn = agentpresence.Scene; - } - - // Compose response to other agent. - GridInstantMessage msg = new GridInstantMessage(); - msg.toAgentID = m_pendingFriendRequests[transactionID].UUID; - msg.fromAgentID = agentID.UUID; - msg.fromAgentName = client.FirstName + " " + client.LastName; - msg.fromAgentSession = client.SessionId.UUID; - msg.fromGroup = false; - msg.imSessionID = transactionID.UUID; - msg.message = agentID.UUID.ToString(); - msg.ParentEstateID = 0; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID; - msg.dialog = (byte)39;// Approved friend request - msg.Position = new sLLVector3(); - msg.offline = (byte)0; - msg.binaryBucket = new byte[0]; - // We don't really care which scene we pipe it through, it goes to the shared IM Module and/or the database - - SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); - SceneAgentIn.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint)1); - m_pendingFriendRequests.Remove(transactionID); - - // TODO: Inform agent that the friend is online - } - } - - private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders) - { - if (m_pendingFriendRequests.ContainsKey(transactionID)) - { - Scene SceneAgentIn = m_scene[0]; - - // Found Pending Friend Request with that Transaction.. - ScenePresence agentpresence = GetPresenceFromAgentID(agentID); - if (agentpresence != null) - { - SceneAgentIn = agentpresence.Scene; - } - // Compose response to other agent. - GridInstantMessage msg = new GridInstantMessage(); - msg.toAgentID = m_pendingFriendRequests[transactionID].UUID; - msg.fromAgentID = agentID.UUID; - msg.fromAgentName = client.FirstName + " " + client.LastName; - msg.fromAgentSession = client.SessionId.UUID; - msg.fromGroup = false; - msg.imSessionID = transactionID.UUID; - msg.message = agentID.UUID.ToString(); - msg.ParentEstateID = 0; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID; - msg.dialog = (byte)40;// Deny friend request - msg.Position = new sLLVector3(); - msg.offline = (byte)0; - msg.binaryBucket = new byte[0]; - SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); - m_pendingFriendRequests.Remove(transactionID); - } - } - - private void OnTerminateFriendship(IClientAPI client, LLUUID agent, LLUUID exfriendID) - { - m_scene[0].StoreRemoveFriendship(agent, exfriendID); - // TODO: Inform the client that the ExFriend is offline - } - - private void OnGridInstantMessage(GridInstantMessage msg) - { - // Trigger the above event handler - OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), - new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, - msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, - new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID), - msg.binaryBucket); - } - #endregion - private ScenePresence GetPresenceFromAgentID(LLUUID AgentID) - { - ScenePresence returnAgent = null; - lock (m_scene) - { - ScenePresence queryagent = null; - for (int i = 0; i < m_scene.Count; i++) - { - queryagent = m_scene[i].GetScenePresence(AgentID); - if (queryagent != null) - { - if (!queryagent.IsChildAgent) - { - returnAgent = queryagent; - break; - } - } - } - } - return returnAgent; - - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "FriendsModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using libsecondlife.Packets; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Avatar.Friends +{ + public class FriendsModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private List m_scene = new List(); + + Dictionary m_rootAgents = new Dictionary(); + + Dictionary m_pendingFriendRequests = new Dictionary(); + + Dictionary> FriendLists = new Dictionary>(); + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_scene) + { + if (m_scene.Count == 0) + { + scene.AddXmlRPCHandler("presence_update", processPresenceUpdate); + } + + if (!m_scene.Contains(scene)) + m_scene.Add(scene); + } + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage; + scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; + scene.EventManager.OnClientClosed += ClientLoggedOut; + } + public XmlRpcResponse processPresenceUpdate(XmlRpcRequest req) + { + m_log.Info("[FRIENDS]: Got Notification about a user! OMG"); + return new XmlRpcResponse(); + } + 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 + // + // The base set of friends are added when the user signs on in their XMLRPC response + // Generated by LoginService. The friends are retreived from the database by the UserManager + + // Subscribe to instant messages + + client.OnInstantMessage += OnInstantMessage; + client.OnApproveFriendRequest += OnApprovedFriendRequest; + client.OnDenyFriendRequest += OnDenyFriendRequest; + client.OnTerminateFriendship += OnTerminateFriendship; + + List fl = new List(); + + //bool addFLback = false; + + lock (FriendLists) + { + if (FriendLists.ContainsKey(client.AgentId)) + { + fl = FriendLists[client.AgentId]; + } + else + { + fl = m_scene[0].GetFriendList(client.AgentId); + + //lock (FriendLists) + //{ + if (!FriendLists.ContainsKey(client.AgentId)) + FriendLists.Add(client.AgentId, fl); + //} + } + } + + List UpdateUsers = new List(); + + foreach (FriendListItem f in fl) + { + if (m_rootAgents.ContainsKey(f.Friend)) + { + if (f.onlinestatus == false) + { + UpdateUsers.Add(f.Friend); + f.onlinestatus = true; + } + } + } + foreach (LLUUID user in UpdateUsers) + { + ScenePresence av = GetPresenceFromAgentID(user); + if (av != null) + { + List usrfl = new List(); + + lock (FriendLists) + { + usrfl = FriendLists[user]; + } + + lock (usrfl) + { + foreach (FriendListItem fli in usrfl) + { + if (fli.Friend == client.AgentId) + { + fli.onlinestatus = true; + OnlineNotificationPacket onp = new OnlineNotificationPacket(); + OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[1]; + OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = client.AgentId; + onpb[0] = onpbl; + onp.AgentBlock = onpb; + av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task); + } + } + } + } + } + + if (UpdateUsers.Count > 0) + { + OnlineNotificationPacket onp = new OnlineNotificationPacket(); + OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[UpdateUsers.Count]; + for (int i = 0; i < UpdateUsers.Count; i++) + { + OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = UpdateUsers[i]; + onpb[i] = onpbl; + } + onp.AgentBlock = onpb; + client.OutPacket(onp, ThrottleOutPacketType.Task); + } + + + + + } + + private void ClientLoggedOut(LLUUID AgentId) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(AgentId)) + { + m_rootAgents.Remove(AgentId); + m_log.Info("[FRIEND]: Removing " + AgentId + ". Agent logged out."); + } + } + List lfli = new List(); + lock (FriendLists) + { + if (FriendLists.ContainsKey(AgentId)) + { + lfli = FriendLists[AgentId]; + } + } + List updateUsers = new List(); + foreach (FriendListItem fli in lfli) + { + if (fli.onlinestatus == true) + { + updateUsers.Add(fli.Friend); + } + } + lock (updateUsers) + { + for (int i = 0; i < updateUsers.Count; i++) + { + List flfli = new List(); + try + { + + lock (FriendLists) + { + if (FriendLists.ContainsKey(updateUsers[i])) + flfli = FriendLists[updateUsers[i]]; + } + } + catch (IndexOutOfRangeException) + { + // Ignore the index out of range exception. + // This causes friend lists to get out of sync slightly.. however + // prevents a sim crash. + m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off"); + } + + for (int j = 0; j < flfli.Count; j++) + { + try + { + if (flfli[i].Friend == AgentId) + { + flfli[i].onlinestatus = false; + } + + } + + catch (IndexOutOfRangeException) + { + // Ignore the index out of range exception. + // This causes friend lists to get out of sync slightly.. however + // prevents a sim crash. + m_log.Info("[FRIEND]: Unable to enumerate last friendlist user. User logged off"); + } + } + + } + + for (int i = 0; i < updateUsers.Count; i++) + { + ScenePresence av = GetPresenceFromAgentID(updateUsers[i]); + if (av != null) + { + + OfflineNotificationPacket onp = new OfflineNotificationPacket(); + OfflineNotificationPacket.AgentBlockBlock[] onpb = new OfflineNotificationPacket.AgentBlockBlock[1]; + OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock(); + onpbl.AgentID = AgentId; + onpb[0] = onpbl; + onp.AgentBlock = onpb; + av.ControllingClient.OutPacket(onp, ThrottleOutPacketType.Task); + } + } + } + lock (FriendLists) + { + FriendLists.Remove(AgentId); + } + + } + + private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) + { + lock (m_rootAgents) + { + if (m_rootAgents.ContainsKey(avatar.UUID)) + { + if (avatar.RegionHandle != m_rootAgents[avatar.UUID]) + { + m_rootAgents[avatar.UUID] = avatar.RegionHandle; + m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); + if (avatar.JID.Length > 0) + { + JId avatarID = new JId(avatar.JID); + // REST Post XMPP Stanzas! + + } + // Claim User! my user! Mine mine mine! + } + } + else + { + m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); + m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); + } + } + //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); + m_log.Info("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent"); + } + + } + } + + } + #region FriendRequestHandling + private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID, + LLUUID fromAgentSession, LLUUID toAgentID, + LLUUID imSessionID, uint timestamp, string fromAgentName, + string message, byte dialog, bool fromGroup, byte offline, + uint ParentEstateID, LLVector3 Position, LLUUID RegionID, + byte[] binaryBucket) + { + // Friend Requests go by Instant Message.. using the dialog param + // https://wiki.secondlife.com/wiki/ImprovedInstantMessage + + // 38 == Offer friendship + if (dialog == (byte)38) + { + LLUUID friendTransactionID = LLUUID.Random(); + + m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); + + m_log.Info("[FRIEND]: 38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = fromAgentID.UUID; + msg.fromAgentSession = fromAgentSession.UUID; + msg.toAgentID = toAgentID.UUID; + msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here + m_log.Info("[FRIEND]: Filling Session: " + msg.imSessionID.ToString()); + msg.timestamp = timestamp; + if (client != null) + { + msg.fromAgentName = client.FirstName + " " + client.LastName;// fromAgentName; + } + else + { + msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it + } + msg.message = message; + msg.dialog = dialog; + msg.fromGroup = fromGroup; + msg.offline = offline; + msg.ParentEstateID = ParentEstateID; + msg.Position = new sLLVector3(Position); + msg.RegionID = RegionID.UUID; + msg.binaryBucket = binaryBucket; + // We don't really care which scene we pipe it through. + m_scene[0].TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + } + + // 39 == Accept Friendship + if (dialog == (byte)39) + { + m_log.Info("[FRIEND]: 39 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); + } + + // 40 == Decline Friendship + if (dialog == (byte)40) + { + m_log.Info("[FRIEND]: 40 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); + } + } + + private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders) + { + if (m_pendingFriendRequests.ContainsKey(transactionID)) + { + // Found Pending Friend Request with that Transaction.. + Scene SceneAgentIn = m_scene[0]; + + // Found Pending Friend Request with that Transaction.. + ScenePresence agentpresence = GetPresenceFromAgentID(agentID); + if (agentpresence != null) + { + SceneAgentIn = agentpresence.Scene; + } + + // Compose response to other agent. + GridInstantMessage msg = new GridInstantMessage(); + msg.toAgentID = m_pendingFriendRequests[transactionID].UUID; + msg.fromAgentID = agentID.UUID; + msg.fromAgentName = client.FirstName + " " + client.LastName; + msg.fromAgentSession = client.SessionId.UUID; + msg.fromGroup = false; + msg.imSessionID = transactionID.UUID; + msg.message = agentID.UUID.ToString(); + msg.ParentEstateID = 0; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID; + msg.dialog = (byte)39;// Approved friend request + msg.Position = new sLLVector3(); + msg.offline = (byte)0; + msg.binaryBucket = new byte[0]; + // We don't really care which scene we pipe it through, it goes to the shared IM Module and/or the database + + SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + SceneAgentIn.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint)1); + m_pendingFriendRequests.Remove(transactionID); + + // TODO: Inform agent that the friend is online + } + } + + private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders) + { + if (m_pendingFriendRequests.ContainsKey(transactionID)) + { + Scene SceneAgentIn = m_scene[0]; + + // Found Pending Friend Request with that Transaction.. + ScenePresence agentpresence = GetPresenceFromAgentID(agentID); + if (agentpresence != null) + { + SceneAgentIn = agentpresence.Scene; + } + // Compose response to other agent. + GridInstantMessage msg = new GridInstantMessage(); + msg.toAgentID = m_pendingFriendRequests[transactionID].UUID; + msg.fromAgentID = agentID.UUID; + msg.fromAgentName = client.FirstName + " " + client.LastName; + msg.fromAgentSession = client.SessionId.UUID; + msg.fromGroup = false; + msg.imSessionID = transactionID.UUID; + msg.message = agentID.UUID.ToString(); + msg.ParentEstateID = 0; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.RegionID = SceneAgentIn.RegionInfo.RegionID.UUID; + msg.dialog = (byte)40;// Deny friend request + msg.Position = new sLLVector3(); + msg.offline = (byte)0; + msg.binaryBucket = new byte[0]; + SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + m_pendingFriendRequests.Remove(transactionID); + } + } + + private void OnTerminateFriendship(IClientAPI client, LLUUID agent, LLUUID exfriendID) + { + m_scene[0].StoreRemoveFriendship(agent, exfriendID); + // TODO: Inform the client that the ExFriend is offline + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Trigger the above event handler + OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), + new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, + msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, + new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID), + msg.binaryBucket); + } + #endregion + private ScenePresence GetPresenceFromAgentID(LLUUID AgentID) + { + ScenePresence returnAgent = null; + lock (m_scene) + { + ScenePresence queryagent = null; + for (int i = 0; i < m_scene.Count; i++) + { + queryagent = m_scene[i].GetScenePresence(AgentID); + if (queryagent != null) + { + if (!queryagent.IsChildAgent) + { + returnAgent = queryagent; + break; + } + } + } + } + return returnAgent; + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "FriendsModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/GroupsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs similarity index 93% rename from OpenSim/Region/Environment/Modules/GroupsModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs index b23bb91678..4b28ad749e 100644 --- a/OpenSim/Region/Environment/Modules/GroupsModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Groups/GroupsModule.cs @@ -1,278 +1,278 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class GroupsModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private List m_scene = new List(); - private Dictionary m_iclientmap = new Dictionary(); - private Dictionary m_groupmap = new Dictionary(); - private Dictionary m_grouplistmap = new Dictionary(); - - public void Initialise(Scene scene, IConfigSource config) - { - lock (m_scene) - { - m_scene.Add(scene); - } - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnClientClosed += OnClientClosed; - scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage; - //scene.EventManager. - } - - 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 - // - // The base set of friends are added when the user signs on in their XMLRPC response - // Generated by LoginService. The friends are retreived from the database by the UserManager - - // Subscribe to instant messages - client.OnInstantMessage += OnInstantMessage; - client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; - lock (m_iclientmap) - { - if (!m_iclientmap.ContainsKey(client.AgentId)) - { - m_iclientmap.Add(client.AgentId, client); - } - } - GroupData OpenSimulatorGroup = new GroupData(); - OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester"; - OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120"); - OpenSimulatorGroup.GroupMembers.Add(client.AgentId); - OpenSimulatorGroup.groupName = "OpenSimulator Testing"; - OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome; - OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester"); - lock (m_groupmap) - { - if (!m_groupmap.ContainsKey(client.AgentId)) - { - m_groupmap.Add(client.AgentId, OpenSimulatorGroup); - } - } - GroupList testGroupList = new GroupList(); - testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120")); - - lock (m_grouplistmap) - { - if (!m_grouplistmap.ContainsKey(client.AgentId)) - { - m_grouplistmap.Add(client.AgentId, testGroupList); - } - } - m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group"); - } - - private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID) - { - string firstname = remoteClient.FirstName; - string lastname = remoteClient.LastName; - - LLUUID ActiveGroupID = LLUUID.Zero; - uint ActiveGroupPowers = 0; - string ActiveGroupName = ""; - string ActiveGroupTitle = ""; - - bool foundUser = false; - - lock (m_iclientmap) - { - if (m_iclientmap.ContainsKey(remoteClient.AgentId)) - { - foundUser = true; - } - } - if (foundUser) - { - lock (m_groupmap) - { - if (m_groupmap.ContainsKey(remoteClient.AgentId)) - { - GroupData grp = m_groupmap[remoteClient.AgentId]; - if (grp != null) - { - ActiveGroupID = grp.GroupID; - ActiveGroupName = grp.groupName; - ActiveGroupPowers = grp.groupPowers; - ActiveGroupTitle = grp.ActiveGroupTitle; - } - - //remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle); - - } - } - } - - } - - private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID, - LLUUID fromAgentSession, LLUUID toAgentID, - LLUUID imSessionID, uint timestamp, string fromAgentName, - string message, byte dialog, bool fromGroup, byte offline, - uint ParentEstateID, LLVector3 Position, LLUUID RegionID, - byte[] binaryBucket) - { - } - - private void OnGridInstantMessage(GridInstantMessage msg) - { - // Trigger the above event handler - OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), - new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, - msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, - new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID), - msg.binaryBucket); - } - - private void OnClientClosed(LLUUID agentID) - { - lock (m_iclientmap) - { - if (m_iclientmap.ContainsKey(agentID)) - { - IClientAPI cli = m_iclientmap[agentID]; - if (cli != null) - { - m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName); - } - else - { - m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString()); - } - m_iclientmap.Remove(agentID); - } - } - - lock (m_groupmap) - { - if (m_groupmap.ContainsKey(agentID)) - { - m_groupmap.Remove(agentID); - } - } - - lock (m_grouplistmap) - { - if (m_grouplistmap.ContainsKey(agentID)) - { - m_grouplistmap.Remove(agentID); - } - } - GC.Collect(); - } - - public void PostInitialise() - { - } - - public void Close() - { - m_log.Info("[GROUP]: Shutting down group module."); - lock (m_iclientmap) - { - m_iclientmap.Clear(); - } - - lock (m_groupmap) - { - m_groupmap.Clear(); - } - - lock (m_grouplistmap) - { - m_grouplistmap.Clear(); - } - GC.Collect(); - } - - public string Name - { - get { return "GroupsModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - } - - public class GroupData - { - public LLUUID GroupID; - public string groupName; - public string ActiveGroupTitle; - public List GroupTitles; - public List GroupMembers; - public uint groupPowers = (uint)(GroupPowers.LandAllowLandmark | GroupPowers.LandAllowSetHome); - - public GroupPowers ActiveGroupPowers - { - set - { - groupPowers = (uint) value; - } - get - { - return (GroupPowers)groupPowers; - } - } - - public GroupData() - { - GroupTitles = new List(); - GroupMembers = new List(); - } - - } - - public class GroupList - { - public List m_GroupList; - public GroupList() - { - m_GroupList = new List(); - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Avatar.Groups +{ + public class GroupsModule : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private List m_scene = new List(); + private Dictionary m_iclientmap = new Dictionary(); + private Dictionary m_groupmap = new Dictionary(); + private Dictionary m_grouplistmap = new Dictionary(); + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_scene) + { + m_scene.Add(scene); + } + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnClientClosed += OnClientClosed; + scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage; + //scene.EventManager. + } + + 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 + // + // The base set of friends are added when the user signs on in their XMLRPC response + // Generated by LoginService. The friends are retreived from the database by the UserManager + + // Subscribe to instant messages + client.OnInstantMessage += OnInstantMessage; + client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; + lock (m_iclientmap) + { + if (!m_iclientmap.ContainsKey(client.AgentId)) + { + m_iclientmap.Add(client.AgentId, client); + } + } + GroupData OpenSimulatorGroup = new GroupData(); + OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester"; + OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120"); + OpenSimulatorGroup.GroupMembers.Add(client.AgentId); + OpenSimulatorGroup.groupName = "OpenSimulator Testing"; + OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome; + OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester"); + lock (m_groupmap) + { + if (!m_groupmap.ContainsKey(client.AgentId)) + { + m_groupmap.Add(client.AgentId, OpenSimulatorGroup); + } + } + GroupList testGroupList = new GroupList(); + testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120")); + + lock (m_grouplistmap) + { + if (!m_grouplistmap.ContainsKey(client.AgentId)) + { + m_grouplistmap.Add(client.AgentId, testGroupList); + } + } + m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group"); + } + + private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID) + { + string firstname = remoteClient.FirstName; + string lastname = remoteClient.LastName; + + LLUUID ActiveGroupID = LLUUID.Zero; + uint ActiveGroupPowers = 0; + string ActiveGroupName = ""; + string ActiveGroupTitle = ""; + + bool foundUser = false; + + lock (m_iclientmap) + { + if (m_iclientmap.ContainsKey(remoteClient.AgentId)) + { + foundUser = true; + } + } + if (foundUser) + { + lock (m_groupmap) + { + if (m_groupmap.ContainsKey(remoteClient.AgentId)) + { + GroupData grp = m_groupmap[remoteClient.AgentId]; + if (grp != null) + { + ActiveGroupID = grp.GroupID; + ActiveGroupName = grp.groupName; + ActiveGroupPowers = grp.groupPowers; + ActiveGroupTitle = grp.ActiveGroupTitle; + } + + //remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle); + + } + } + } + + } + + private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID, + LLUUID fromAgentSession, LLUUID toAgentID, + LLUUID imSessionID, uint timestamp, string fromAgentName, + string message, byte dialog, bool fromGroup, byte offline, + uint ParentEstateID, LLVector3 Position, LLUUID RegionID, + byte[] binaryBucket) + { + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Trigger the above event handler + OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), + new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, + msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, + new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID), + msg.binaryBucket); + } + + private void OnClientClosed(LLUUID agentID) + { + lock (m_iclientmap) + { + if (m_iclientmap.ContainsKey(agentID)) + { + IClientAPI cli = m_iclientmap[agentID]; + if (cli != null) + { + m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName); + } + else + { + m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString()); + } + m_iclientmap.Remove(agentID); + } + } + + lock (m_groupmap) + { + if (m_groupmap.ContainsKey(agentID)) + { + m_groupmap.Remove(agentID); + } + } + + lock (m_grouplistmap) + { + if (m_grouplistmap.ContainsKey(agentID)) + { + m_grouplistmap.Remove(agentID); + } + } + GC.Collect(); + } + + public void PostInitialise() + { + } + + public void Close() + { + m_log.Info("[GROUP]: Shutting down group module."); + lock (m_iclientmap) + { + m_iclientmap.Clear(); + } + + lock (m_groupmap) + { + m_groupmap.Clear(); + } + + lock (m_grouplistmap) + { + m_grouplistmap.Clear(); + } + GC.Collect(); + } + + public string Name + { + get { return "GroupsModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + } + + public class GroupData + { + public LLUUID GroupID; + public string groupName; + public string ActiveGroupTitle; + public List GroupTitles; + public List GroupMembers; + public uint groupPowers = (uint)(GroupPowers.LandAllowLandmark | GroupPowers.LandAllowSetHome); + + public GroupPowers ActiveGroupPowers + { + set + { + groupPowers = (uint) value; + } + get + { + return (GroupPowers)groupPowers; + } + } + + public GroupData() + { + GroupTitles = new List(); + GroupMembers = new List(); + } + + } + + public class GroupList + { + public List m_GroupList; + public GroupList() + { + m_GroupList = new List(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/InstantMessageModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs similarity index 89% rename from OpenSim/Region/Environment/Modules/InstantMessageModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs index 6e13b735f1..1b82837311 100644 --- a/OpenSim/Region/Environment/Modules/InstantMessageModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs @@ -1,159 +1,157 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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; -using System.Collections.Generic; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class InstantMessageModule : IRegionModule - { - private List m_scenes = new List(); - private Hashtable m_RegionInfoCache = new Hashtable(); - - public void Initialise(Scene scene, IConfigSource config) - { - lock (m_scenes) - { - if (m_scenes.Count == 0) - { - //scene.AddXmlRPCHandler("avatar_location_update", processPresenceUpdate); - } - - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage; - } - } - } - - private void OnNewClient(IClientAPI client) - { - client.OnInstantMessage += OnInstantMessage; - } - - private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID, - LLUUID fromAgentSession, LLUUID toAgentID, - LLUUID imSessionID, uint timestamp, string fromAgentName, - string message, byte dialog, bool fromGroup, byte offline, - uint ParentEstateID, LLVector3 Position, LLUUID RegionID, - byte[] binaryBucket) - { - bool dialogHandledElsewhere - = ((dialog == (byte)38) || (dialog == (byte)39) || (dialog == (byte)40) - || dialog == (byte)InstantMessageDialog.InventoryOffered - || dialog == (byte)InstantMessageDialog.InventoryAccepted - || dialog == (byte)InstantMessageDialog.InventoryDeclined); - - // IM dialogs need to be pre-processed and have their sessionID filled by the server - // so the sim can match the transaction on the return packet. - - // Don't send a Friend Dialog IM with a LLUUID.Zero session. - if (!(dialogHandledElsewhere && imSessionID == LLUUID.Zero)) - { - // Try root avatar only first - foreach (Scene scene in m_scenes) - { - if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) - { - // Local message - ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; - if (!user.IsChildAgent) - { - user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, - toAgentID, imSessionID, fromAgentName, dialog, - timestamp); - // Message sent - return; - } - } - } - - // try child avatar second - foreach (Scene scene in m_scenes) - { - if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) - { - // Local message - ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; - - user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, - toAgentID, imSessionID, fromAgentName, dialog, - timestamp); - // Message sent - return; - - } - } - - } - - - // Still here, try send via Grid - // TODO - } - - // Trusty OSG1 called method. This method also gets called from the FriendsModule - // Turns out the sim has to send an instant message to the user to get it to show an accepted friend. - - private void OnGridInstantMessage(GridInstantMessage msg) - { - // Trigger the above event handler - OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), - new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, - msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, - new LLVector3(msg.Position.x,msg.Position.y,msg.Position.z), new LLUUID(msg.RegionID), - msg.binaryBucket); - - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "InstantMessageModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage +{ + public class InstantMessageModule : IRegionModule + { + private readonly List m_scenes = new List(); + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_scenes) + { + if (m_scenes.Count == 0) + { + //scene.AddXmlRPCHandler("avatar_location_update", processPresenceUpdate); + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage; + } + } + } + + private void OnNewClient(IClientAPI client) + { + client.OnInstantMessage += OnInstantMessage; + } + + private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID, + LLUUID fromAgentSession, LLUUID toAgentID, + LLUUID imSessionID, uint timestamp, string fromAgentName, + string message, byte dialog, bool fromGroup, byte offline, + uint ParentEstateID, LLVector3 Position, LLUUID RegionID, + byte[] binaryBucket) + { + bool dialogHandledElsewhere + = ((dialog == 38) || (dialog == 39) || (dialog == 40) + || dialog == (byte)InstantMessageDialog.InventoryOffered + || dialog == (byte)InstantMessageDialog.InventoryAccepted + || dialog == (byte)InstantMessageDialog.InventoryDeclined); + + // IM dialogs need to be pre-processed and have their sessionID filled by the server + // so the sim can match the transaction on the return packet. + + // Don't send a Friend Dialog IM with a LLUUID.Zero session. + if (!(dialogHandledElsewhere && imSessionID == LLUUID.Zero)) + { + // Try root avatar only first + foreach (Scene scene in m_scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; + if (!user.IsChildAgent) + { + user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, + toAgentID, imSessionID, fromAgentName, dialog, + timestamp); + // Message sent + return; + } + } + } + + // try child avatar second + foreach (Scene scene in m_scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; + + user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, + toAgentID, imSessionID, fromAgentName, dialog, + timestamp); + // Message sent + return; + + } + } + + } + + + // Still here, try send via Grid + // TODO + } + + // Trusty OSG1 called method. This method also gets called from the FriendsModule + // Turns out the sim has to send an instant message to the user to get it to show an accepted friend. + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Trigger the above event handler + OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), + new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, + msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, + new LLVector3(msg.Position.x,msg.Position.y,msg.Position.z), new LLUUID(msg.RegionID), + msg.binaryBucket); + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "InstantMessageModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/InventoryModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/InventoryModule.cs similarity index 80% rename from OpenSim/Region/Environment/Modules/InventoryModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Inventory/InventoryModule.cs index ff5a02cba4..42c6238967 100644 --- a/OpenSim/Region/Environment/Modules/InventoryModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Inventory/InventoryModule.cs @@ -1,216 +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.Collections.Generic; -using System.Reflection; -using libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class InventoryModule : IRegionModule - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - - /// - /// We need to keep track of the pending item offers between clients since the itemId offered only - /// occurs in the initial offer message, not the accept message. So this dictionary links - /// IM Session Ids to ItemIds - /// - private IDictionary m_pendingOffers = new Dictionary(); - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - scene.EventManager.OnNewClient += OnNewClient; - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "InventoryModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - private void OnNewClient(IClientAPI client) - { - // Inventory giving is conducted via instant message - client.OnInstantMessage += OnInstantMessage; - } - - private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID, - LLUUID fromAgentSession, LLUUID toAgentID, - LLUUID imSessionID, uint timestamp, string fromAgentName, - string message, byte dialog, bool fromGroup, byte offline, - uint ParentEstateID, LLVector3 Position, LLUUID RegionID, - byte[] binaryBucket) - { - if (dialog == (byte)InstantMessageDialog.InventoryOffered) - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}", - client.AgentId, client.Name, toAgentID); - - if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) - { - ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; - - if (!user.IsChildAgent) - { - //byte[] rawId = new byte[16]; - - // First byte of the array is probably the item type - // Next 16 bytes are the UUID - //Array.Copy(binaryBucket, 1, rawId, 0, 16); - - //LLUUID itemId = new LLUUID(new Guid(rawId)); - LLUUID itemId = new LLUUID(binaryBucket, 1); - - m_log.DebugFormat( - "[AGENT INVENTORY]: ItemId for giving is {0}", itemId); - - m_pendingOffers[imSessionID] = itemId; - - user.ControllingClient.SendInstantMessage( - fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, - dialog, timestamp, binaryBucket); - - return; - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", - toAgentID, client.AgentId, client.Name, message); - } - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", - toAgentID, client.AgentId, client.Name, message); - } - } - else if (dialog == (byte)InstantMessageDialog.InventoryAccepted) - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}", - client.AgentId, client.Name, toAgentID); - - if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) - { - ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; - - if (!user.IsChildAgent) - { - user.ControllingClient.SendInstantMessage( - fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, - dialog, timestamp, binaryBucket); - - if (m_pendingOffers.ContainsKey(imSessionID)) - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]); - - // Since the message originates from the accepting client, the toAgentID is - // the agent giving the item. - m_scene.GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]); - - m_pendingOffers.Remove(imSessionID); - } - else - { - m_log.ErrorFormat( - "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept", - imSessionID); - } - - return; - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", - toAgentID, client.AgentId, client.Name, message); - } - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", - toAgentID, client.AgentId, client.Name, message); - } - } - else if (dialog == (byte)InstantMessageDialog.InventoryDeclined) - { - if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) - { - ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; - - if (!user.IsChildAgent) - { - user.ControllingClient.SendInstantMessage( - fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, - dialog, timestamp, binaryBucket); - - if (m_pendingOffers.ContainsKey(imSessionID)) - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]); - - m_pendingOffers.Remove(imSessionID); - } - else - { - m_log.ErrorFormat( - "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline", - imSessionID); - } - } - } - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Avatar.Inventory +{ + public class InventoryModule : IRegionModule + { + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + + /// + /// We need to keep track of the pending item offers between clients since the itemId offered only + /// occurs in the initial offer message, not the accept message. So this dictionary links + /// IM Session Ids to ItemIds + /// + private IDictionary m_pendingOffers = new Dictionary(); + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + scene.EventManager.OnNewClient += OnNewClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "InventoryModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + private void OnNewClient(IClientAPI client) + { + // Inventory giving is conducted via instant message + client.OnInstantMessage += OnInstantMessage; + } + + private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID, + LLUUID fromAgentSession, LLUUID toAgentID, + LLUUID imSessionID, uint timestamp, string fromAgentName, + string message, byte dialog, bool fromGroup, byte offline, + uint ParentEstateID, LLVector3 Position, LLUUID RegionID, + byte[] binaryBucket) + { + if (dialog == (byte)InstantMessageDialog.InventoryOffered) + { + m_log.DebugFormat( + "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}", + client.AgentId, client.Name, toAgentID); + + if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) + { + ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; + + if (!user.IsChildAgent) + { + //byte[] rawId = new byte[16]; + + // First byte of the array is probably the item type + // Next 16 bytes are the UUID + //Array.Copy(binaryBucket, 1, rawId, 0, 16); + + //LLUUID itemId = new LLUUID(new Guid(rawId)); + LLUUID itemId = new LLUUID(binaryBucket, 1); + + m_log.DebugFormat( + "[AGENT INVENTORY]: ItemId for giving is {0}", itemId); + + m_pendingOffers[imSessionID] = itemId; + + user.ControllingClient.SendInstantMessage( + fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, + dialog, timestamp, binaryBucket); + + return; + } + else + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", + toAgentID, client.AgentId, client.Name, message); + } + } + else + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", + toAgentID, client.AgentId, client.Name, message); + } + } + else if (dialog == (byte)InstantMessageDialog.InventoryAccepted) + { + m_log.DebugFormat( + "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}", + client.AgentId, client.Name, toAgentID); + + if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) + { + ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; + + if (!user.IsChildAgent) + { + user.ControllingClient.SendInstantMessage( + fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, + dialog, timestamp, binaryBucket); + + if (m_pendingOffers.ContainsKey(imSessionID)) + { + m_log.DebugFormat( + "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]); + + // Since the message originates from the accepting client, the toAgentID is + // the agent giving the item. + m_scene.GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]); + + m_pendingOffers.Remove(imSessionID); + } + else + { + m_log.ErrorFormat( + "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept", + imSessionID); + } + + return; + } + else + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", + toAgentID, client.AgentId, client.Name, message); + } + } + else + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", + toAgentID, client.AgentId, client.Name, message); + } + } + else if (dialog == (byte)InstantMessageDialog.InventoryDeclined) + { + if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) + { + ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; + + if (!user.IsChildAgent) + { + user.ControllingClient.SendInstantMessage( + fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, + dialog, timestamp, binaryBucket); + + if (m_pendingOffers.ContainsKey(imSessionID)) + { + m_log.DebugFormat( + "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]); + + m_pendingOffers.Remove(imSessionID); + } + else + { + m_log.ErrorFormat( + "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline", + imSessionID); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/AvatarProfilesModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs similarity index 90% rename from OpenSim/Region/Environment/Modules/AvatarProfilesModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs index 44b3f8b361..f8b14d3623 100644 --- a/OpenSim/Region/Environment/Modules/AvatarProfilesModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Profiles/AvatarProfilesModule.cs @@ -1,129 +1,129 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class AvatarProfilesModule : IRegionModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Scene m_scene; - - public AvatarProfilesModule() - { - } - - 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; } - } - - 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, LLUUID avatarID) - { - // FIXME: finish adding fields such as url, masking, etc. - LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000"); - UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID); - if (null != profile) - { - remoteClient.SendAvatarProperties(profile.ID, profile.AboutText, - Util.ToDateTime(profile.Created).ToString(), - String.Empty, profile.FirstLifeAboutText, profile.CanDoMask, - profile.FirstLifeImage, profile.Image, String.Empty, 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.UpdateUserProfileProperties(Profile)) - { - RequestAvatarProperty(remoteClient, newProfile.ID); - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.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() + { + } + + 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; } + } + + 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, LLUUID avatarID) + { + // FIXME: finish adding fields such as url, masking, etc. + LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000"); + UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID); + if (null != profile) + { + remoteClient.SendAvatarProperties(profile.ID, profile.AboutText, + Util.ToDateTime(profile.Created).ToString(), + String.Empty, profile.FirstLifeAboutText, profile.CanDoMask, + profile.FirstLifeImage, profile.Image, String.Empty, 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.UpdateUserProfileProperties(Profile)) + { + RequestAvatarProperty(remoteClient, newProfile.ID); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/AsteriskVoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs similarity index 93% rename from OpenSim/Region/Environment/Modules/AsteriskVoiceModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs index 38c0c1d7a6..0d7de78e46 100644 --- a/OpenSim/Region/Environment/Modules/AsteriskVoiceModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Voice/AsterixVoice/AsteriskVoiceModule.cs @@ -1,285 +1,285 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Servers; -using OpenSim.Region.Capabilities; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using Caps=OpenSim.Region.Capabilities.Caps; - -namespace OpenSim.Region.Environment.Modules -{ - public class AsteriskVoiceModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - private IConfig m_config; - private string m_asterisk; - private string m_asterisk_password; - private string m_asterisk_salt; - private int m_asterisk_timeout; - private string m_sipDomain; - private string m_confDomain; - - private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; - private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; - - 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; } - } - - public void OnRegisterCaps(LLUUID 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) - { - return ParcelVoiceInfoRequest(request, path, param, - agentID, caps); - })); - caps.RegisterHandler("ProvisionVoiceAccountRequest", - new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, - delegate(string request, string path, string param) - { - return ProvisionVoiceAccountRequest(request, path, param, - agentID, caps); - })); - } - - /// - /// Callback for a client request for ParcelVoiceInfo - /// - /// - /// - /// - /// - /// - /// - public string ParcelVoiceInfoRequest(string request, string path, string param, - LLUUID 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, - LLUUID 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"; - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Capabilities; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using Caps=OpenSim.Region.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 Scene m_scene; + private IConfig m_config; + private string m_asterisk; + private string m_asterisk_password; + private string m_asterisk_salt; + private int m_asterisk_timeout; + private string m_sipDomain; + private string m_confDomain; + + private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; + private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; + + 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; } + } + + public void OnRegisterCaps(LLUUID 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) + { + return ParcelVoiceInfoRequest(request, path, param, + agentID, caps); + })); + caps.RegisterHandler("ProvisionVoiceAccountRequest", + new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, + delegate(string request, string path, string param) + { + return ProvisionVoiceAccountRequest(request, path, param, + agentID, caps); + })); + } + + /// + /// Callback for a client request for ParcelVoiceInfo + /// + /// + /// + /// + /// + /// + /// + public string ParcelVoiceInfoRequest(string request, string path, string param, + LLUUID 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, + LLUUID 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"; + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/VoiceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs similarity index 89% rename from OpenSim/Region/Environment/Modules/VoiceModule.cs rename to OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs index 106becd727..8b7c3d0858 100644 --- a/OpenSim/Region/Environment/Modules/VoiceModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Voice/SIPVoice/SIPVoiceModule.cs @@ -1,197 +1,197 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Servers; -using OpenSim.Region.Capabilities; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using Caps=OpenSim.Region.Capabilities.Caps; - -namespace OpenSim.Region.Environment.Modules -{ - public class VoiceModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - private IConfig m_config; - private string m_sipDomain; - - private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; - private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; - - 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; } - } - - public void OnRegisterCaps(LLUUID 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) - { - return ParcelVoiceInfoRequest(request, path, param, - agentID, caps); - })); - caps.RegisterHandler("ProvisionVoiceAccountRequest", - new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, - delegate(string request, string path, string param) - { - return ProvisionVoiceAccountRequest(request, path, param, - agentID, caps); - })); - } - - /// - /// Callback for a client request for ParcelVoiceInfo - /// - /// - /// - /// - /// - /// - /// - public string ParcelVoiceInfoRequest(string request, string path, string param, - LLUUID 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.ToString(), 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, - LLUUID 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; - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Capabilities; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using Caps=OpenSim.Region.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 Scene m_scene; + private IConfig m_config; + private string m_sipDomain; + + private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; + private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; + + 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; } + } + + public void OnRegisterCaps(LLUUID 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) + { + return ParcelVoiceInfoRequest(request, path, param, + agentID, caps); + })); + caps.RegisterHandler("ProvisionVoiceAccountRequest", + new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, + delegate(string request, string path, string param) + { + return ProvisionVoiceAccountRequest(request, path, param, + agentID, caps); + })); + } + + /// + /// Callback for a client request for ParcelVoiceInfo + /// + /// + /// + /// + /// + /// + /// + public string ParcelVoiceInfoRequest(string request, string path, string param, + LLUUID 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, + LLUUID 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; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/CommanderTestModule.cs b/OpenSim/Region/Environment/Modules/CommanderTestModule.cs deleted file mode 100644 index a30de7336e..0000000000 --- a/OpenSim/Region/Environment/Modules/CommanderTestModule.cs +++ /dev/null @@ -1,89 +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 Nini.Config; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Modules.ModuleFramework; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class CommanderTestModule : IRegionModule, ICommandableModule - { - Commander m_commander = new Commander("CommanderTest"); - Scene m_scene; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - } - - private void InterfaceHelloWorld(Object[] args) - { - Console.WriteLine("Hello World"); - } - - public void PostInitialise() - { - Command testCommand = new Command("hello", InterfaceHelloWorld, "Says a simple debugging test string"); - testCommand.AddArgument("world", "Write world here", "string"); - - m_commander.RegisterCommand("hello", testCommand); - - // Register me - m_scene.RegisterModuleCommander("commandertest", m_commander); - } - - public void Close() - { - } - - public string Name - { - get { return "CommanderTestModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region ICommandableModule Members - - public ICommander CommandInterface - { - get { throw new NotImplementedException(); } - } - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/Communications/Interregion/IInterregionModule.cs b/OpenSim/Region/Environment/Modules/Communications/Interregion/IInterregionModule.cs deleted file mode 100644 index 713b46aaa9..0000000000 --- a/OpenSim/Region/Environment/Modules/Communications/Interregion/IInterregionModule.cs +++ /dev/null @@ -1,15 +0,0 @@ -using OpenSim.Framework; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.Communications.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(); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Communications/Interregion/InterregionModule.cs b/OpenSim/Region/Environment/Modules/Communications/Interregion/InterregionModule.cs deleted file mode 100644 index 8d040c4498..0000000000 --- a/OpenSim/Region/Environment/Modules/Communications/Interregion/InterregionModule.cs +++ /dev/null @@ -1,174 +0,0 @@ -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.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.Communications.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 List m_myLocations = new List(); - - private readonly Dictionary m_neighbourInterfaces = new Dictionary(); - private readonly Dictionary m_neighbourRemote = new Dictionary(); - private IConfigSource m_config; - private RemotingObject m_myRemote; - - private Object m_lockObject = new object(); - private TcpChannel m_tcpChannel; - private int m_tcpPort = 10101; - private bool m_enabled = false; - - #region IRegionModule Members - - //TODO: This prevents us from registering new scenes after PostInitialise if we want comms updated. - public void Initialise(Scene scene, IConfigSource source) - { - if (m_enabled) - { - m_myLocations.Add(new Location((int) scene.RegionInfo.RegionLocX, - (int) scene.RegionInfo.RegionLocY)); - m_config = source; - - scene.RegisterModuleInterface(this); - } - } - - //TODO: This prevents us from registering new scenes after PostInitialise if we want comms updated. - public void PostInitialise() - { - if (m_enabled) - { - try - { - m_tcpPort = m_config.Configs["Comms"].GetInt("remoting_port", m_tcpPort); - } - catch - { - } - - internal_CreateRemotingObjects(); - } - } - - public void Close() - { - ChannelServices.UnregisterChannel(m_tcpChannel); - } - - public string Name - { - get { return "InterregionModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - 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 RegisterRemoteRegion(string uri) - { - RegisterRemotingInterface((RemotingObject) Activator.GetObject(typeof (RemotingObject), uri)); - } - - 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; - } - } - - 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(); - } - else - { - 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); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Communications/Interregion/RemotingObject.cs b/OpenSim/Region/Environment/Modules/Communications/Interregion/RemotingObject.cs deleted file mode 100644 index a735677f40..0000000000 --- a/OpenSim/Region/Environment/Modules/Communications/Interregion/RemotingObject.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using OpenSim.Framework; - -namespace OpenSim.Region.Environment.Modules.Communications.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."); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/EmailModule.cs b/OpenSim/Region/Environment/Modules/EmailModule.cs deleted file mode 100644 index b629f4c7b9..0000000000 --- a/OpenSim/Region/Environment/Modules/EmailModule.cs +++ /dev/null @@ -1,33 +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. - */ - -namespace OpenSim.Region.Environment.Modules -{ - internal class EmailModule - { - } -} diff --git a/OpenSim/Region/Environment/Modules/ExportSerialiser/ExportSerialisationModule.cs b/OpenSim/Region/Environment/Modules/ExportSerialiser/ExportSerialisationModule.cs deleted file mode 100644 index 91770af637..0000000000 --- a/OpenSim/Region/Environment/Modules/ExportSerialiser/ExportSerialisationModule.cs +++ /dev/null @@ -1,168 +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 Nini.Config; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Modules.ModuleFramework; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.ExportSerialiser -{ - public class ExportSerialisationModule : IRegionModule, IRegionSerialiser - { - 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("Export", 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 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() + "/"); - } - } - } - - private void InterfaceSaveAllRegions(Object[] args) - { - foreach (Scene region in m_regions) - { - List results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/"); - } - } - - private void LoadCommanderCommands() - { - Command serialiseSceneCommand = new Command("save", 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", InterfaceSaveAllRegions, "Saves all regions into the exports directory."); - - m_commander.RegisterCommand("save", serialiseSceneCommand); - m_commander.RegisterCommand("save-all", serialiseAllScenesCommand); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ExportSerialiser/IFileSerialiser.cs b/OpenSim/Region/Environment/Modules/ExportSerialiser/IFileSerialiser.cs deleted file mode 100644 index 77a418fd93..0000000000 --- a/OpenSim/Region/Environment/Modules/ExportSerialiser/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.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.ExportSerialiser -{ - internal interface IFileSerialiser - { - string WriteToFile(Scene scene, string dir); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ExportSerialiser/IRegionSerialiser.cs b/OpenSim/Region/Environment/Modules/ExportSerialiser/IRegionSerialiser.cs deleted file mode 100644 index e1721ff785..0000000000 --- a/OpenSim/Region/Environment/Modules/ExportSerialiser/IRegionSerialiser.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.Collections.Generic; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.ExportSerialiser -{ - public interface IRegionSerialiser - { - List SerialiseRegion(Scene scene, string saveDir); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ExportSerialiser/SerialiseObjects.cs b/OpenSim/Region/Environment/Modules/ExportSerialiser/SerialiseObjects.cs deleted file mode 100644 index 277370da14..0000000000 --- a/OpenSim/Region/Environment/Modules/ExportSerialiser/SerialiseObjects.cs +++ /dev/null @@ -1,123 +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.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.ExportSerialiser -{ - 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 - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ExportSerialiser/SerialiseTerrain.cs b/OpenSim/Region/Environment/Modules/ExportSerialiser/SerialiseTerrain.cs deleted file mode 100644 index c4790c2419..0000000000 --- a/OpenSim/Region/Environment/Modules/ExportSerialiser/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.Terrain; -using OpenSim.Region.Environment.Modules.Terrain.FileLoaders; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.ExportSerialiser -{ - 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/LandManagement/LandChannel.cs b/OpenSim/Region/Environment/Modules/LandManagement/LandChannel.cs deleted file mode 100644 index e2414b0863..0000000000 --- a/OpenSim/Region/Environment/Modules/LandManagement/LandChannel.cs +++ /dev/null @@ -1,1008 +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 Axiom.Math; -using libsecondlife; -using libsecondlife.Packets; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Environment.Modules.LandManagement -{ - public class LandChannel : ILandChannel - { - #region Constants - - //Land types set with flags in ParcelOverlay. - //Only one of these can be used. - public const byte LAND_TYPE_PUBLIC = (byte)0; //Equals 00000000 - public const byte LAND_TYPE_OWNED_BY_OTHER = (byte)1; //Equals 00000001 - public const byte LAND_TYPE_OWNED_BY_GROUP = (byte)2; //Equals 00000010 - public const byte LAND_TYPE_OWNED_BY_REQUESTER = (byte)3; //Equals 00000011 - public const byte LAND_TYPE_IS_FOR_SALE = (byte)4; //Equals 00000100 - public const byte LAND_TYPE_IS_BEING_AUCTIONED = (byte)5; //Equals 00000101 - - //Flags that when set, a border on the given side will be placed - //NOTE: North and East is assumable by the west and south sides (if land to east has a west border, then I have an east border; etc) - //This took forever to figure out -- jeesh. /blame LL for even having to send these - public const byte LAND_FLAG_PROPERTY_BORDER_WEST = (byte)64; //Equals 01000000 - public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = (byte)128; //Equals 10000000 - - //RequestResults (I think these are right, they seem to work): - public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land - public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land - - //ParcelSelectObjects - public const int LAND_SELECT_OBJECTS_OWNER = 2; - public const int LAND_SELECT_OBJECTS_GROUP = 4; - public const int LAND_SELECT_OBJECTS_OTHER = 8; - - //These are other constants. Yay! - public const int START_LAND_LOCAL_ID = 1; - - public const float BAN_LINE_SAFETY_HIEGHT = 100; - - #endregion - - private Scene m_scene; - - private Dictionary landList = new Dictionary(); - private int lastLandLocalID = START_LAND_LOCAL_ID - 1; - private int[,] landIDList = new int[64, 64]; - - private bool landPrimCountTainted = false; - - private bool m_allowedForcefulBans = true; - public bool allowedForcefulBans - { - get - { - return m_allowedForcefulBans; - } - set - { - m_allowedForcefulBans = value; - } - } - - public LandChannel(Scene scene) - { - m_scene = scene; - landIDList.Initialize(); - } - #region Land Object From Storage Functions - - public void IncomingLandObjectsFromStorage(List data) - { - for (int i = 0; i < data.Count; i++) - { - //try - //{ - IncomingLandObjectFromStorage(data[i]); - //} - //catch (Exception ex) - //{ - //m_log.Error("[LandManager]: IncomingLandObjectsFromStorage: Exception: " + ex.ToString()); - //throw ex; - //} - } - //foreach (LandData parcel in data) - //{ - // IncomingLandObjectFromStorage(parcel); - //} - } - - 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 NoLandDataFromStorage() - { - resetSimLandObjects(); - } - - #endregion - - #region Parcel Add/Remove/Get/Create - - /// - /// Creates a basic Parcel object without an owner (a zeroed key) - /// - /// - public ILandObject createBaseLand() - { - return new LandObject(LLUUID.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 new_land) - { - lastLandLocalID++; - new_land.landData.localID = lastLandLocalID; - landList.Add(lastLandLocalID, (LandObject)new_land.Copy()); - - - bool[,] landBitmap = new_land.getLandBitmap(); - int x, y; - for (x = 0; x < 64; x++) - { - for (y = 0; y < 64; y++) - { - if (landBitmap[x, y]) - { - landIDList[x, y] = lastLandLocalID; - } - } - } - landList[lastLandLocalID].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) - { - int x, y; - for (x = 0; x < 64; x++) - { - for (y = 0; y < 64; y++) - { - if (landIDList[x, y] == local_id) - { - return; - //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); - } - } - } - - m_scene.EventManager.TriggerLandObjectRemoved(landList[local_id].landData.globalID); - landList.Remove(local_id); - } - - public void updateLandObject(int local_id, LandData newData) - { - if (landList.ContainsKey(local_id)) - { - landList[local_id].landData = newData.Copy(); - m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, landList[local_id]); - } - } - - private void performFinalLandJoin(ILandObject master, ILandObject slave) - { - int x, y; - bool[,] landBitmapSlave = slave.getLandBitmap(); - for (x = 0; x < 64; x++) - { - for (y = 0; y < 64; y++) - { - if (landBitmapSlave[x, y]) - { - landIDList[x, y] = master.landData.localID; - } - } - } - - removeLandObject(slave.landData.localID); - updateLandObject(master.landData.localID, master.landData); - } - - /// - /// 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) / Convert.ToDouble(4.0))); - y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / Convert.ToDouble(4.0))); - } - catch (OverflowException) - { - return null; - } - - if (x >= 64 || y >= 64 || x < 0 || y < 0) - { - return null; - } - else - { - return landList[landIDList[x, y]]; - } - } - - public ILandObject getLandObject(int parcelLocalID) - { - lock (landList) - { - if (landList.ContainsKey(parcelLocalID)) - { - return landList[parcelLocalID]; - } - } - 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); - } - else - { - return landList[landIDList[x / 4, y / 4]]; - } - } - - #endregion - - #region Parcel Modification - - /// - /// Subdivides a piece of land - /// - /// West Point - /// South Point - /// East Point - /// North Point - /// LLUUID of user who is trying to subdivide - /// Returns true if successful - private bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID 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 = null; - try - { - startLandObject = getLandObject(start_x, start_y); - } - catch (Exception) - { - //m_log.Error("[LAND]: " + "Unable to get land object for subdivision at x: " + start_x + " y:" + start_y); - } - if (startLandObject == null) return false; //No such land object at the beginning - - //Loop through the points - try - { - int totalX = end_x - start_x; - int totalY = end_y - start_y; - int x, y; - for (y = 0; y < totalY; y++) - { - for (x = 0; x < totalX; x++) - { - ILandObject tempLandObject = getLandObject(start_x + x, start_y + y); - if (tempLandObject == null) return false; //No such land object at that point - if (tempLandObject != startLandObject) return false; //Subdividing over 2 land objects; no-no - } - } - } - catch (Exception) - { - return false; //Exception. For now, lets skip subdivision - } - - //If we are still here, then they are subdividing within one piece of land - //Check owner - if (startLandObject.landData.ownerID != attempting_user_id) - { - return false; //They cant do this! - } - - //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) - ILandObject newLand = startLandObject.Copy(); - newLand.landData.landName = "Subdivision of " + newLand.landData.landName; - newLand.landData.globalID = LLUUID.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; - landList[startLandObjectIndex].setLandBitmap( - newLand.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false)); - landList[startLandObjectIndex].forceUpdateLandInfo(); - - setPrimsTainted(); - - //Now add the new land object - ILandObject result = addLandObject(newLand); - updateLandObject(startLandObject.landData.localID, startLandObject.landData); - result.sendLandUpdateToAvatarsOverMe(); - - - return true; - } - - /// - /// 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 - /// LLUUID of the avatar trying to join the land objects - /// Returns true if successful - private bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id) - { - end_x -= 4; - end_y -= 4; - - List selectedLandObjects = new List(); - int stepXSelected = 0; - int stepYSelected = 0; - for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4) - { - for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4) - { - ILandObject p = null; - try - { - p = getLandObject(stepXSelected, stepYSelected); - } - catch (Exception) - { - //m_log.Error("[LAND]: " + "Unable to get land object for subdivision at x: " + stepXSelected + " y:" + stepYSelected); - } - if (p != null) - { - if (!selectedLandObjects.Contains(p)) - { - selectedLandObjects.Add(p); - } - } - } - } - ILandObject masterLandObject = selectedLandObjects[0]; - selectedLandObjects.RemoveAt(0); - - - if (selectedLandObjects.Count < 1) - { - return false; //Only one piece of land selected - } - if (masterLandObject.landData.ownerID != attempting_user_id) - { - return false; //Not the same owner - } - foreach (ILandObject p in selectedLandObjects) - { - if (p.landData.ownerID != masterLandObject.landData.ownerID) - { - return false; //Over multiple users. TODO: make this just ignore this piece of land? - } - } - foreach (ILandObject slaveLandObject in selectedLandObjects) - { - landList[masterLandObject.landData.localID].setLandBitmap( - slaveLandObject.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap())); - performFinalLandJoin(masterLandObject, slaveLandObject); - } - - - setPrimsTainted(); - - masterLandObject.sendLandUpdateToAvatarsOverMe(); - - return true; - } - - public void resetAllLandPrimCounts() - { - foreach (LandObject p in landList.Values) - { - p.resetLandPrimCounts(); - } - } - - public void setPrimsTainted() - { - landPrimCountTainted = true; - } - - public bool isLandPrimCountTainted() - { - return landPrimCountTainted; - } - - public void addPrimToLandPrimCounts(SceneObjectGroup obj) - { - LLVector3 position = obj.AbsolutePosition; - ILandObject landUnderPrim = getLandObject(position.X, position.Y); - if (landUnderPrim != null) - { - landUnderPrim.addPrimToCount(obj); - } - } - - public void removePrimFromLandPrimCounts(SceneObjectGroup obj) - { - foreach (LandObject p in landList.Values) - { - p.removePrimFromCount(obj); - } - } - - public void finalizeLandPrimCountUpdate() - { - //Get Simwide prim count for owner - Dictionary> landOwnersAndParcels = new Dictionary>(); - foreach (LandObject p in 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 (LLUUID 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() - { - foreach (EntityBase obj in m_scene.Entities.Values) - { - if (obj is SceneObjectGroup) - { - m_scene.EventManager.TriggerParcelPrimCountAdd((SceneObjectGroup)obj); - } - } - } - - public void performParcelPrimCountUpdate() - { - resetAllLandPrimCounts(); - m_scene.EventManager.TriggerParcelPrimCountUpdate(); - finalizeLandPrimCountUpdate(); - landPrimCountTainted = false; - } - #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; - int x, y = 0; - byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; - int byteArrayCount = 0; - int sequenceID = 0; - ParcelOverlayPacket packet; - - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - byte tempByte = (byte)0; //This represents the byte for the current 4x4 - ILandObject currentParcelBlock = null; - - try - { - currentParcelBlock = getLandObject(x * 4, y * 4); - } - catch (Exception) - { - //m_log.Warn("[LAND]: " + "unable to get land at x: " + (x * 4) + " y: " + (y * 4)); - } - - - if (currentParcelBlock != null) - { - if (currentParcelBlock.landData.ownerID == remote_client.AgentId) - { - //Owner Flag - tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_REQUESTER); - } - else if (currentParcelBlock.landData.salePrice > 0 && - (currentParcelBlock.landData.authBuyerID == LLUUID.Zero || - currentParcelBlock.landData.authBuyerID == remote_client.AgentId)) - { - //Sale Flag - tempByte = Convert.ToByte(tempByte | LAND_TYPE_IS_FOR_SALE); - } - else if (currentParcelBlock.landData.ownerID == LLUUID.Zero) - { - //Public Flag - tempByte = Convert.ToByte(tempByte | LAND_TYPE_PUBLIC); - } - else - { - //Other Flag - tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_OTHER); - } - - - //Now for border control - try - { - 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 | LAND_FLAG_PROPERTY_BORDER_WEST); - } - else if (westParcel != null && westParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST); - } - - if (y == 0) - { - tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH); - } - else if (southParcel != null && southParcel != currentParcelBlock) - { - tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH); - } - - byteArray[byteArrayCount] = tempByte; - byteArrayCount++; - if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) - { - byteArrayCount = 0; - packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); - packet.ParcelData.Data = byteArray; - packet.ParcelData.SequenceID = sequenceID; - remote_client.OutPacket((Packet)packet, ThrottleOutPacketType.Task); - sequenceID++; - byteArray = new byte[LAND_BLOCKS_PER_PACKET]; - } - } - catch (Exception) - { - //m_log.Debug("[LAND]: Skipped Land checks because avatar is out of bounds: " + e.Message); - } - } - } - } - } - - 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 x, y, i; - int inc_x = end_x - start_x; - int inc_y = end_y - start_y; - for (x = 0; x < inc_x; x++) - { - for (y = 0; y < inc_y; y++) - { - - ILandObject currentParcel = null; - try - { - currentParcel = getLandObject(start_x + x, start_y + y); - } - catch (Exception) - { - //m_log.Warn("[LAND]: " + "unable to get land at x: " + (start_x + x) + " y: " + (start_y + y)); - } - if (currentParcel != null) - { - if (!temp.Contains(currentParcel)) - { - currentParcel.forceUpdateLandInfo(); - temp.Add(currentParcel); - } - } - } - } - - int requestResult = LAND_RESULT_SINGLE; - if (temp.Count > 1) - { - requestResult = LAND_RESULT_MULTIPLE; - } - - for (i = 0; i < temp.Count; i++) - { - temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client); - } - - - sendParcelOverlay(remote_client); - } - - public void handleParcelPropertiesUpdateRequest(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client) - { - if (landList.ContainsKey(packet.ParcelData.LocalID)) - { - landList[packet.ParcelData.LocalID].updateLandProperties(packet, 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, IClientAPI remote_client) - { - landList[local_id].sendForceObjectSelect(local_id, request_type, remote_client); - } - - public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client) - { - landList[local_id].sendLandObjectOwners(remote_client); - } - - #endregion - - /// - /// 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 - landList.Clear(); - lastLandLocalID = START_LAND_LOCAL_ID - 1; - landIDList.Initialize(); - - ILandObject fullSimParcel = new LandObject(LLUUID.Zero, false, m_scene); - - fullSimParcel.setLandBitmap(fullSimParcel.getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); - fullSimParcel.landData.ownerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; - - addLandObject(fullSimParcel); - } - - public List parcelsNearPoint(LLVector3 position) - { - List parcelsNear = new List(); - int x, y; - for (x = -4; x <= 4; x += 4) - { - for (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. <3 OpenSim Developers"); - - 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! <3 OpenSim Developers"); - } - } - - public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, LLUUID regionID) - { - if (m_scene.RegionInfo.RegionID == regionID) - { - if (landList[localLandID] != null) - { - ILandObject parcelAvatarIsEntering = landList[localLandID]; - if (avatar.AbsolutePosition.Z < 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!). <3 OpenSim Developers"); - } - 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(-30000, false, (int)ParcelManager.ParcelResult.Single, avatar); - return; //Only send one - } - else if (checkBan.isRestrictedFromLand(avatar.AgentId)) - { - checkBan.sendLandProperties(-40000, false, (int)ParcelManager.ParcelResult.Single, avatar); - return; //Only send one - } - } - return; - } - } - } - - public void sendLandUpdate(ScenePresence avatar, bool force) - { - ILandObject over = null; - try - { - 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)))); - } - catch (Exception) - { - //m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " + 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 < 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 < 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 >= BAN_LINE_SAFETY_HIEGHT) - { - avatar.lastKnownAllowedPosition = - new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); - } - } - } - - - public void handleParcelAccessRequest(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID, - int landLocalID, IClientAPI remote_client) - { - if (landList.ContainsKey(landLocalID)) - { - landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client); - } - } - - public void handleParcelAccessUpdateRequest(LLUUID agentID, LLUUID sessionID, uint flags, int landLocalID, - List entries, - IClientAPI remote_client) - { - if (landList.ContainsKey(landLocalID)) - { - if (agentID == landList[landLocalID].landData.ownerID) - { - landList[landLocalID].updateAccessList(flags, entries, remote_client); - } - } - else - { - Console.WriteLine("INVALID LOCAL LAND ID"); - } - } - - // 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) - { - lock (landList) - { - if (landList.ContainsKey(e.parcelLocalID)) - { - landList[e.parcelLocalID].updateLandSold(e.agentId, e.groupId, e.groupOwned, (uint)e.transactionID, e.parcelPrice, e.parcelArea); - return; - } - } - } - } - - // 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 (landList) - { - if (landList.ContainsKey(e.parcelLocalID)) - { - lob = landList[e.parcelLocalID]; - } - } - if (lob != null) - { - LLUUID AuthorizedID = lob.landData.authBuyerID; - int saleprice = lob.landData.salePrice; - LLUUID pOwnerID = lob.landData.ownerID; - - bool landforsale = ((lob.landData.landFlags & (uint)(Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects)) != 0); - if ((AuthorizedID == LLUUID.Zero || AuthorizedID == e.agentId) && e.parcelPrice >= saleprice && landforsale) - { - lock (e) - { - e.parcelOwnerID = pOwnerID; - e.landValidated = true; - - } - - } - } - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/LandManagement/LandManagementModule.cs b/OpenSim/Region/Environment/Modules/LandManagement/LandManagementModule.cs deleted file mode 100644 index 1c36c0c842..0000000000 --- a/OpenSim/Region/Environment/Modules/LandManagement/LandManagementModule.cs +++ /dev/null @@ -1,85 +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 Nini.Config; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.LandManagement -{ - public class LandManagementModule : IRegionModule - { - private LandChannel landChannel; - private Scene m_scene; - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - landChannel = new LandChannel(scene); - - m_scene.EventManager.OnParcelPrimCountAdd += landChannel.addPrimToLandPrimCounts; - m_scene.EventManager.OnParcelPrimCountUpdate += landChannel.updateLandPrimCounts; - m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(landChannel.handleAvatarChangingParcel); - m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(landChannel.handleAnyClientMovement); - m_scene.EventManager.OnValidateLandBuy += landChannel.handleLandValidationRequest; - m_scene.EventManager.OnLandBuy += landChannel.handleLandBuyRequest; - - lock (m_scene) - { - m_scene.LandChannel = (ILandChannel)landChannel; - } - } - - public void PostInitialise() - { - - } - - public void Close() - { - - } - - public string Name - { - get { return "LandManagementModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - - - - - #endregion - } -} diff --git a/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs b/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs deleted file mode 100644 index da42c217b1..0000000000 --- a/OpenSim/Region/Environment/Modules/LandManagement/LandObject.cs +++ /dev/null @@ -1,947 +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 libsecondlife; -using libsecondlife.Packets; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.LandManagement -{ - - #region LandObject Class - - /// - /// 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); - - protected LandData m_landData = new LandData(); - protected List primsOverMe = new List(); - protected Scene m_scene; - - private bool[,] m_landBitmap = new bool[64,64]; - - 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 LLUUID regionUUID - { - get { return m_scene.RegionInfo.RegionID; } - } - - #endregion - - - #region Constructors - - public LandObject(LLUUID 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; - } - - #endregion - - #region Packet Request Handling - - /// - /// Sends land properties as requested - /// - /// ID sent by client for them to keep track of - /// Bool sent by client for them to use - /// Object representing the client - public void sendLandProperties(int sequence_id, bool snap_selection, int request_result, - IClientAPI remote_client) - { - ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ParcelProperties); - // TODO: don't create new blocks if recycling an old packet - - updatePacket.ParcelData.AABBMax = landData.AABBMax; - updatePacket.ParcelData.AABBMin = landData.AABBMin; - updatePacket.ParcelData.Area = landData.area; - updatePacket.ParcelData.AuctionID = landData.auctionID; - updatePacket.ParcelData.AuthBuyerID = landData.authBuyerID; //unemplemented - - updatePacket.ParcelData.Bitmap = landData.landBitmapByteArray; - - updatePacket.ParcelData.Desc = Helpers.StringToField(landData.landDesc); - updatePacket.ParcelData.Category = (byte) landData.category; - updatePacket.ParcelData.ClaimDate = landData.claimDate; - updatePacket.ParcelData.ClaimPrice = landData.claimPrice; - updatePacket.ParcelData.GroupID = landData.groupID; - updatePacket.ParcelData.GroupPrims = landData.groupPrims; - updatePacket.ParcelData.IsGroupOwned = landData.isGroupOwned; - updatePacket.ParcelData.LandingType = (byte) landData.landingType; - updatePacket.ParcelData.LocalID = landData.localID; - if (landData.area > 0) - { - updatePacket.ParcelData.MaxPrims = - Convert.ToInt32( - Math.Round((Convert.ToDecimal(landData.area)/Convert.ToDecimal(65536))*m_scene.objectCapacity* - Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor))); - } - else - { - updatePacket.ParcelData.MaxPrims = 0; - } - updatePacket.ParcelData.MediaAutoScale = landData.mediaAutoScale; - updatePacket.ParcelData.MediaID = landData.mediaID; - updatePacket.ParcelData.MediaURL = Helpers.StringToField(landData.mediaURL); - updatePacket.ParcelData.MusicURL = Helpers.StringToField(landData.musicURL); - updatePacket.ParcelData.Name = Helpers.StringToField(landData.landName); - updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented - updatePacket.ParcelData.OtherCount = 0; //unemplemented - updatePacket.ParcelData.OtherPrims = landData.otherPrims; - updatePacket.ParcelData.OwnerID = landData.ownerID; - updatePacket.ParcelData.OwnerPrims = landData.ownerPrims; - updatePacket.ParcelData.ParcelFlags = landData.landFlags; - updatePacket.ParcelData.ParcelPrimBonus = m_scene.RegionInfo.EstateSettings.objectBonusFactor; - updatePacket.ParcelData.PassHours = landData.passHours; - updatePacket.ParcelData.PassPrice = landData.passPrice; - updatePacket.ParcelData.PublicCount = 0; //unemplemented - - uint regionFlags = (uint) m_scene.RegionInfo.EstateSettings.regionFlags; - updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint) Simulator.RegionFlags.DenyAnonymous) > - 0); - updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint) Simulator.RegionFlags.DenyIdentified) > - 0); - updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint) Simulator.RegionFlags.DenyTransacted) > - 0); - updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint) Simulator.RegionFlags.RestrictPushObject) > - 0); - - updatePacket.ParcelData.RentPrice = 0; - updatePacket.ParcelData.RequestResult = request_result; - updatePacket.ParcelData.SalePrice = landData.salePrice; - updatePacket.ParcelData.SelectedPrims = landData.selectedPrims; - updatePacket.ParcelData.SelfCount = 0; //unemplemented - updatePacket.ParcelData.SequenceID = sequence_id; - if (landData.simwideArea > 0) - { - updatePacket.ParcelData.SimWideMaxPrims = - Convert.ToInt32( - Math.Round((Convert.ToDecimal(landData.simwideArea) / Convert.ToDecimal(65536)) * m_scene.objectCapacity * - Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor))); - } - else - { - updatePacket.ParcelData.SimWideMaxPrims = 0; - } - updatePacket.ParcelData.SimWideTotalPrims = landData.simwidePrims; - updatePacket.ParcelData.SnapSelection = snap_selection; - updatePacket.ParcelData.SnapshotID = landData.snapshotID; - updatePacket.ParcelData.Status = (byte) landData.landStatus; - updatePacket.ParcelData.TotalPrims = landData.ownerPrims + landData.groupPrims + landData.otherPrims + - landData.selectedPrims; - updatePacket.ParcelData.UserLocation = landData.userLocation; - updatePacket.ParcelData.UserLookAt = landData.userLookAt; - remote_client.OutPacket((Packet) updatePacket, ThrottleOutPacketType.Task); - } - - public void updateLandProperties(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client) - { - if (remote_client.AgentId == landData.ownerID) - { - //Needs later group support - LandData newData = landData.Copy(); - newData.authBuyerID = packet.ParcelData.AuthBuyerID; - newData.category = (Parcel.ParcelCategory) packet.ParcelData.Category; - newData.landDesc = Helpers.FieldToUTF8String(packet.ParcelData.Desc); - newData.groupID = packet.ParcelData.GroupID; - newData.landingType = packet.ParcelData.LandingType; - newData.mediaAutoScale = packet.ParcelData.MediaAutoScale; - newData.mediaID = packet.ParcelData.MediaID; - newData.mediaURL = Helpers.FieldToUTF8String(packet.ParcelData.MediaURL); - newData.musicURL = Helpers.FieldToUTF8String(packet.ParcelData.MusicURL); - newData.landName = Helpers.FieldToUTF8String(packet.ParcelData.Name); - newData.landFlags = packet.ParcelData.ParcelFlags; - newData.passHours = packet.ParcelData.PassHours; - newData.passPrice = packet.ParcelData.PassPrice; - newData.salePrice = packet.ParcelData.SalePrice; - newData.snapshotID = packet.ParcelData.SnapshotID; - newData.userLocation = packet.ParcelData.UserLocation; - newData.userLookAt = packet.ParcelData.UserLookAt; - - m_scene.LandChannel.updateLandObject(landData.localID, newData); - - sendLandUpdateToAvatarsOverMe(); - } - } - public void updateLandSold(LLUUID avatarID, LLUUID 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 = LLUUID.Zero; - newData.landFlags &= ~(uint)(Parcel.ParcelFlags.ForSale | Parcel.ParcelFlags.ForSaleObjects | Parcel.ParcelFlags.SellParcelObjects); - m_scene.LandChannel.updateLandObject(landData.localID, newData); - - sendLandUpdateToAvatarsOverMe(); - } - - public bool isEitherBannedOrRestricted(LLUUID avatar) - { - if (isBannedFromLand(avatar)) - { - return true; - } - else if (isRestrictedFromLand(avatar)) - { - return true; - } - return false; - } - - public bool isBannedFromLand(LLUUID avatar) - { - if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseBanList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = ParcelManager.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(LLUUID avatar) - { - if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseAccessList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = ParcelManager.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((int)Math.Max(255,Math.Min(0,Math.Round(avatars[i].AbsolutePosition.X))), - (int)Math.Max(255,Math.Min(0,Math.Round(avatars[i].AbsolutePosition.Y)))); - } - 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) - { - sendLandUpdateToClient(avatars[i].ControllingClient); - } - } - } - } - - #endregion - - #region AccessList Functions - - public ParcelAccessListReplyPacket.ListBlock[] createAccessListArrayByFlag(ParcelManager.AccessList flag) - { - List list = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in landData.parcelAccessList) - { - if (entry.Flags == flag) - { - ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock(); - - listBlock.Flags = (uint) 0; - listBlock.ID = entry.AgentID; - listBlock.Time = 0; - - list.Add(listBlock); - } - } - - if (list.Count == 0) - { - ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock(); - - listBlock.Flags = (uint) 0; - listBlock.ID = LLUUID.Zero; - listBlock.Time = 0; - - list.Add(listBlock); - } - return list.ToArray(); - } - - public void sendAccessList(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID, - IClientAPI remote_client) - { - ParcelAccessListReplyPacket replyPacket; - - if (flags == (uint) ParcelManager.AccessList.Access || flags == (uint) ParcelManager.AccessList.Both) - { - replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); - replyPacket.Data.AgentID = agentID; - replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Access; - replyPacket.Data.LocalID = landData.localID; - replyPacket.Data.SequenceID = 0; - - replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Access); - remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task); - } - - if (flags == (uint) ParcelManager.AccessList.Ban || flags == (uint) ParcelManager.AccessList.Both) - { - replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); - replyPacket.Data.AgentID = agentID; - replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Ban; - replyPacket.Data.LocalID = landData.localID; - replyPacket.Data.SequenceID = 0; - - replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Ban); - remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task); - } - } - - public void updateAccessList(uint flags, List entries, IClientAPI remote_client) - { - LandData newData = landData.Copy(); - - if (entries.Count == 1 && entries[0].AgentID == LLUUID.Zero) - { - entries.Clear(); - } - - List toRemove = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in newData.parcelAccessList) - { - if (entry.Flags == (ParcelManager.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 = (ParcelManager.AccessList) flags; - - if (!newData.parcelAccessList.Contains(temp)) - { - newData.parcelAccessList.Add(temp); - } - } - - m_scene.LandChannel.updateLandObject(landData.localID, newData); - } - - #endregion - - #region Update Functions - - /// - /// 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 LLVector3((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 LLVector3((float)(max_x * 4), (float)(max_y * 4), - (float)m_scene.Heightmap[tx, ty]); - landData.area = tempArea; - } - - public void updateLandBitmapByteArray() - { - landData.landBitmapByteArray = convertLandBitmapToBytes(); - } - - /// - /// Update all settings in land such as area, bitmap byte array, etc - /// - public void forceUpdateLandInfo() - { - updateAABBAndAreaValues(); - updateLandBitmapByteArray(); - } - - public void setLandBitmapFromByteArray() - { - landBitmap = convertBytesToLandBitmap(); - } - - #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; - } - - /// - /// 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.landBitmapByteArray[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; - } - - /// - /// 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; - } - - #endregion - - #region Object Select and Object Owner Listing - - public void sendForceObjectSelect(int local_id, int request_type, IClientAPI remote_client) - { - List resultLocalIDs = new List(); - 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 == LandManager.LAND_SELECT_OBJECTS_GROUP && ...) // TODO: group support - // { - // } - else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER && - obj.OwnerID != remote_client.AgentId) - { - resultLocalIDs.Add(obj.LocalId); - } - } - } - - - bool firstCall = true; - int MAX_OBJECTS_PER_PACKET = 251; - ForceObjectSelectPacket pack = (ForceObjectSelectPacket) PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); - // TODO: don't create new blocks if recycling an old packet - ForceObjectSelectPacket.DataBlock[] data; - while (resultLocalIDs.Count > 0) - { - if (firstCall) - { - pack._Header.ResetList = true; - firstCall = false; - } - else - { - pack._Header.ResetList = false; - } - - if (resultLocalIDs.Count > MAX_OBJECTS_PER_PACKET) - { - data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; - } - else - { - data = new ForceObjectSelectPacket.DataBlock[resultLocalIDs.Count]; - } - - int i; - for (i = 0; i < MAX_OBJECTS_PER_PACKET && resultLocalIDs.Count > 0; i++) - { - data[i] = new ForceObjectSelectPacket.DataBlock(); - data[i].LocalID = Convert.ToUInt32(resultLocalIDs[0]); - resultLocalIDs.RemoveAt(0); - } - pack.Data = data; - remote_client.OutPacket((Packet) pack, ThrottleOutPacketType.Task); - } - } - - /// - /// 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) - { - Dictionary primCount = new Dictionary(); - ParcelObjectOwnersReplyPacket pack - = (ParcelObjectOwnersReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); - // TODO: don't create new blocks if recycling an old packet - - 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."); - } - } - - int notifyCount = primCount.Count; - - if (notifyCount > 0) - { - if (notifyCount > 32) - { - m_log.InfoFormat( - "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" - + " - a developer might want to investigate whether this is a hard limit", 32); - - notifyCount = 32; - } - - ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock - = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; - - int num = 0; - foreach (LLUUID owner in primCount.Keys) - { - dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); - dataBlock[num].Count = primCount[owner]; - dataBlock[num].IsGroupOwned = false; //TODO: fix me when group support is added - dataBlock[num].OnlineStatus = true; //TODO: fix me later - dataBlock[num].OwnerID = owner; - - num++; - - if (num >= notifyCount) - { - break; - } - } - - pack.Data = dataBlock; - } - - remote_client.OutPacket(pack, ThrottleOutPacketType.Task); - } - - public Dictionary getLandObjectOwners() - { - Dictionary ownersAndCount = new Dictionary(); - foreach (SceneObjectGroup obj in primsOverMe) - { - if (!ownersAndCount.ContainsKey(obj.OwnerID)) - { - ownersAndCount.Add(obj.OwnerID, 0); - } - ownersAndCount[obj.OwnerID] += obj.PrimCount; - } - return ownersAndCount; - } - - #endregion - - #region Object Returning - - public void returnObject(SceneObjectGroup obj) - { - } - - public void returnLandObjects(int type, LLUUID owner) - { - } - - #endregion - - #region Object Adding/Removing from Parcel - - public void resetLandPrimCounts() - { - landData.groupPrims = 0; - landData.ownerPrims = 0; - landData.otherPrims = 0; - landData.selectedPrims = 0; - primsOverMe.Clear(); - } - - public void addPrimToCount(SceneObjectGroup obj) - { - LLUUID 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 - { - landData.otherPrims += prim_count; - } - } - - primsOverMe.Add(obj); - } - - public void removePrimFromCount(SceneObjectGroup obj) - { - if (primsOverMe.Contains(obj)) - { - LLUUID prim_owner = obj.OwnerID; - int prim_count = obj.PrimCount; - - if (prim_owner == landData.ownerID) - { - landData.ownerPrims -= prim_count; - } - else if (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/ModuleFramework/Commander.cs b/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs deleted file mode 100644 index 7ef087dcc3..0000000000 --- a/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs +++ /dev/null @@ -1,308 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.ModuleFramework -{ - /// - /// 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; - - public Command(string name, Action command, string help) - { - m_name = name; - m_command = command; - m_help = help; - } - - #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 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 void ShowConsoleHelp() - { - m_log.Info("== " + Name + " =="); - m_log.Info(m_help); - m_log.Info("= Parameters ="); - foreach (CommandArgument arg in m_args) - { - m_log.Info("* " + arg.Name + " (" + arg.ArgumentType + ")"); - m_log.Info("\t" + arg.HelpText); - } - } - - public void Run(Object[] args) - { - Object[] cleanArgs = new Object[m_args.Count]; - - if (args.Length < cleanArgs.Length) - { - m_log.Error("Missing " + (cleanArgs.Length - args.Length) + " argument(s)"); - ShowConsoleHelp(); - return; - } - if (args.Length > cleanArgs.Length) - { - m_log.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())) - { - m_log.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: - m_log.Error("Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); - break; - } - } - catch (FormatException) - { - m_log.Error("Argument number " + (i + 1) + - " (" + m_args[i].Name + ") must be a valid " + - m_args[i].ArgumentType.ToLower() + "."); - } - 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; } - } - } - - /// - /// 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); - private Dictionary m_commands = new Dictionary(); - private string m_name; - - public Commander(string name) - { - m_name = name; - } - - #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_name + " {\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 != "help") - m_log.Error("Invalid command - No such command exists"); - if (function == "api") - m_log.Info(GenerateRuntimeAPI()); - ShowConsoleHelp(); - } - } - - #endregion - - private void ShowConsoleHelp() - { - m_log.Info("===" + m_name + "==="); - foreach (ICommand com in m_commands.Values) - { - m_log.Info("* " + com.Name + " - " + com.Help); - } - } - - 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/DynamicTextureModule.cs b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs similarity index 90% rename from OpenSim/Region/Environment/Modules/DynamicTextureModule.cs rename to OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs index 02354f166f..63eee976d4 100644 --- a/OpenSim/Region/Environment/Modules/DynamicTextureModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -1,277 +1,277 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using Nini.Config; -using OpenJPEGNet; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - public class DynamicTextureModule : IRegionModule, IDynamicTextureManager - { - private Dictionary RegisteredScenes = new Dictionary(); - - private Dictionary RenderPlugins = - new Dictionary(); - - private Dictionary Updaters = new Dictionary(); - - 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; } - } - - public void RegisterRender(string handleType, IDynamicTextureRender render) - { - if (!RenderPlugins.ContainsKey(handleType)) - { - RenderPlugins.Add(handleType, render); - } - } - - public void ReturnData(LLUUID 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 LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, - string extraParams, int updateTimer) - { - return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); - } - - public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID 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 = LLUUID.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 LLUUID.Zero; - } - - public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, - string extraParams, int updateTimer) - { - return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); - } - - public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID 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 = LLUUID.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 LLUUID.Zero; - } - - public class DynamicTextureUpdater - { - public LLUUID SimUUID; - public LLUUID UpdaterID; - public string ContentType; - public string Url; - public string BodyData; - public LLUUID PrimID; - public int UpdateTimer; - public LLUUID LastAssetID; - public string Params; - public bool BlendWithOldTexture = false; - public bool SetNewFrontAlpha = false; - public byte FrontAlpha = 255; - - public DynamicTextureUpdater() - { - LastAssetID = LLUUID.Zero; - UpdateTimer = 0; - BodyData = null; - } - - public void DataReceived(byte[] data, Scene scene) - { - SceneObjectPart part = scene.GetSceneObjectPart(PrimID); - byte[] assetData; - AssetBase oldAsset = null; - if (BlendWithOldTexture) - { - LLUUID 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); - } - - //TODO delete the last asset(data), if it was a dynamic texture - AssetBase asset = new AssetBase(); - asset.FullID = LLUUID.Random(); - asset.Data = assetData; - asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); - asset.Type = 0; - asset.Description = "dynamic image"; - asset.Local = false; - asset.Temporary = true; - scene.AssetCache.AddAsset(asset); - - LastAssetID = asset.FullID; - - - part.Shape.Textures = new LLObject.TextureEntry(asset.FullID); - part.ScheduleFullUpdate(); - } - -// TODO: unused -// private byte[] BlendTextures(byte[] frontImage, byte[] backImage) -// { -// return BlendTextures(frontImage, backImage, false, 0); -// } - - private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) - { - Bitmap image1 = new Bitmap(OpenJPEG.DecodeToImage(frontImage)); - Bitmap image2 = new Bitmap(OpenJPEG.DecodeToImage(backImage)); - if (setNewAlpha) - { - SetAlpha(ref image1, newAlpha); - } - Bitmap joint = MergeBitMaps(image1, image2); - - return OpenJPEG.EncodeFromImage(joint, true); - } - - 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))); - } - } - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using Nini.Config; +using OpenJPEGNet; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.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(); + + 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; } + } + + public void RegisterRender(string handleType, IDynamicTextureRender render) + { + if (!RenderPlugins.ContainsKey(handleType)) + { + RenderPlugins.Add(handleType, render); + } + } + + public void ReturnData(LLUUID 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 LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, + string extraParams, int updateTimer) + { + return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); + } + + public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID 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 = LLUUID.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 LLUUID.Zero; + } + + public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, + string extraParams, int updateTimer) + { + return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); + } + + public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID 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 = LLUUID.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 LLUUID.Zero; + } + + public class DynamicTextureUpdater + { + public LLUUID SimUUID; + public LLUUID UpdaterID; + public string ContentType; + public string Url; + public string BodyData; + public LLUUID PrimID; + public int UpdateTimer; + public LLUUID LastAssetID; + public string Params; + public bool BlendWithOldTexture = false; + public bool SetNewFrontAlpha = false; + public byte FrontAlpha = 255; + + public DynamicTextureUpdater() + { + LastAssetID = LLUUID.Zero; + UpdateTimer = 0; + BodyData = null; + } + + public void DataReceived(byte[] data, Scene scene) + { + SceneObjectPart part = scene.GetSceneObjectPart(PrimID); + byte[] assetData; + AssetBase oldAsset = null; + if (BlendWithOldTexture) + { + LLUUID 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); + } + + //TODO delete the last asset(data), if it was a dynamic texture + AssetBase asset = new AssetBase(); + asset.FullID = LLUUID.Random(); + asset.Data = assetData; + asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); + asset.Type = 0; + asset.Description = "dynamic image"; + asset.Local = false; + asset.Temporary = true; + scene.AssetCache.AddAsset(asset); + + LastAssetID = asset.FullID; + + + part.Shape.Textures = new LLObject.TextureEntry(asset.FullID); + part.ScheduleFullUpdate(); + } + +// TODO: unused +// private byte[] BlendTextures(byte[] frontImage, byte[] backImage) +// { +// return BlendTextures(frontImage, backImage, false, 0); +// } + + private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) + { + Bitmap image1 = new Bitmap(OpenJPEG.DecodeToImage(frontImage)); + Bitmap image2 = new Bitmap(OpenJPEG.DecodeToImage(backImage)); + if (setNewAlpha) + { + SetAlpha(ref image1, newAlpha); + } + Bitmap joint = MergeBitMaps(image1, image2); + + return OpenJPEG.EncodeFromImage(joint, true); + } + + 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))); + } + } + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs similarity index 95% rename from OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs rename to OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 2de5975663..4977a863fc 100644 --- a/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -1,364 +1,356 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -/***************************************************** - * - * 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 - * its 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 repsonse size? - * Configurable - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules -{ - public class ScriptHTTPRequests : IRegionModule, IHttpRequests - { - private Scene m_scene; - private Queue rpcQueue = new Queue(); - private object HttpListLock = new object(); - private string m_name = "HttpScriptRequests"; - private int httpTimeout = 30000; - - // - private Dictionary m_pendingRequests; - - public ScriptHTTPRequests() - { - } - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - - m_scene.RegisterModuleInterface(this); - - m_pendingRequests = new Dictionary(); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - public LLUUID MakeHttpRequest(string url, string parameters, string body) - { - return LLUUID.Zero; - } - - public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body) - { - LLUUID reqID = LLUUID.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/2; i += 2) - { - switch (Int32.Parse(parms[i])) - { - case HttpRequestClass.HTTP_METHOD: - - htc.httpMethod = parms[i + 1]; - break; - - case HttpRequestClass.HTTP_MIMETYPE: - - htc.httpMIMEType = parms[i + 1]; - break; - - case HttpRequestClass.HTTP_BODY_MAXLENGTH: - - // TODO implement me - break; - - case HttpRequestClass.HTTP_VERIFY_CERT: - - // TODO implement me - break; - } - } - } - - htc.localID = localID; - htc.itemID = itemID; - htc.url = url; - htc.reqID = reqID; - htc.httpTimeout = httpTimeout; - htc.outbound_body = body; - - lock (HttpListLock) - { - m_pendingRequests.Add(reqID, htc); - } - - htc.process(); - - return reqID; - } - - public void StopHttpRequest(uint m_localID, LLUUID 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 HttpRequestClass GetNextCompletedRequest() - { - lock (HttpListLock) - { - foreach (LLUUID luid in m_pendingRequests.Keys) - { - HttpRequestClass tmpReq; - - if (m_pendingRequests.TryGetValue(luid, out tmpReq)) - { - if (tmpReq.finished) - { - return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedRequest(LLUUID id) - { - lock (HttpListLock) - { - HttpRequestClass tmpReq; - if (m_pendingRequests.TryGetValue(id, out tmpReq)) - { - tmpReq.Stop(); - tmpReq = null; - m_pendingRequests.Remove(id); - } - } - } - - } - - // - // HTTP REAQUEST - // This class was originally in LSLLongCmdHandler - // - // TODO: setter/getter methods, maybe pass some in - // constructor - // - - public class HttpRequestClass - { - // Constants for parameters - public const int HTTP_METHOD = 0; - public const int HTTP_MIMETYPE = 1; - public const int HTTP_BODY_MAXLENGTH = 2; - public const int HTTP_VERIFY_CERT = 3; - - // Parameter members and default values - public string httpMethod = "GET"; - public string httpMIMEType = "text/plain;charset=utf-8"; - public int httpBodyMaxLen = 2048; // not implemented - public bool httpVerifyCert = true; // not implemented - - // Request info - public uint localID; - public LLUUID itemID; - public LLUUID reqID; - public int httpTimeout; - public string url; - public string outbound_body; - public DateTime next; - public int status; - public bool finished; - public List response_metadata; - public string response_body; - public HttpWebRequest request; - private Thread httpThread; - - 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; - - 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? - - response_body = sb.ToString(); - } - catch (Exception e) - { - status = 499; - response_body = e.Message; - finished = true; - return; - } - - status = 200; - finished = true; - } - - public void Stop() - { - try - { - httpThread.Abort(); - } - catch (Exception) - { - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * 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 + * its 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 repsonse size? + * Configurable + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest +{ + public class HttpRequestModule : IRegionModule, IHttpRequests + { + private Scene m_scene; + private Queue rpcQueue = new Queue(); + private object HttpListLock = new object(); + private string m_name = "HttpScriptRequests"; + private int httpTimeout = 30000; + + // + private Dictionary m_pendingRequests; + + public HttpRequestModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + + m_scene.RegisterModuleInterface(this); + + m_pendingRequests = new Dictionary(); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public LLUUID MakeHttpRequest(string url, string parameters, string body) + { + return LLUUID.Zero; + } + + public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body) + { + LLUUID reqID = LLUUID.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/2; i += 2) + { + switch (Int32.Parse(parms[i])) + { + case HttpRequestClass.HTTP_METHOD: + + htc.httpMethod = parms[i + 1]; + break; + + case HttpRequestClass.HTTP_MIMETYPE: + + htc.httpMIMEType = parms[i + 1]; + break; + + case HttpRequestClass.HTTP_BODY_MAXLENGTH: + + // TODO implement me + break; + + case HttpRequestClass.HTTP_VERIFY_CERT: + + // TODO implement me + break; + } + } + } + + htc.localID = localID; + htc.itemID = itemID; + htc.url = url; + htc.reqID = reqID; + htc.httpTimeout = httpTimeout; + htc.outbound_body = body; + + lock (HttpListLock) + { + m_pendingRequests.Add(reqID, htc); + } + + htc.process(); + + return reqID; + } + + public void StopHttpRequest(uint m_localID, LLUUID 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 HttpRequestClass GetNextCompletedRequest() + { + lock (HttpListLock) + { + foreach (LLUUID luid in m_pendingRequests.Keys) + { + HttpRequestClass tmpReq; + + if (m_pendingRequests.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.finished) + { + return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedRequest(LLUUID id) + { + lock (HttpListLock) + { + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(id, out tmpReq)) + { + tmpReq.Stop(); + tmpReq = null; + m_pendingRequests.Remove(id); + } + } + } + + } + + public class HttpRequestClass + { + // Constants for parameters + public const int HTTP_METHOD = 0; + public const int HTTP_MIMETYPE = 1; + public const int HTTP_BODY_MAXLENGTH = 2; + public const int HTTP_VERIFY_CERT = 3; + + // Parameter members and default values + public string httpMethod = "GET"; + public string httpMIMEType = "text/plain;charset=utf-8"; + public int httpBodyMaxLen = 2048; // not implemented + public bool httpVerifyCert = true; // not implemented + + // Request info + public uint localID; + public LLUUID itemID; + public LLUUID reqID; + public int httpTimeout; + public string url; + public string outbound_body; + public DateTime next; + public int status; + public bool finished; + public List response_metadata; + public string response_body; + public HttpWebRequest request; + private Thread httpThread; + + 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; + + 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? + + response_body = sb.ToString(); + } + catch (Exception e) + { + status = 499; + response_body = e.Message; + finished = true; + return; + } + + status = 200; + finished = true; + } + + public void Stop() + { + try + { + httpThread.Abort(); + } + catch (Exception) + { + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/LoadImageURLModule.cs b/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs similarity index 96% rename from OpenSim/Region/Environment/Modules/LoadImageURLModule.cs rename to OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs index 6c8b028940..eaf9d36c5f 100644 --- a/OpenSim/Region/Environment/Modules/LoadImageURLModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -1,180 +1,179 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using Nini.Config; -using OpenJPEGNet; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - - public class LoadImageURLModule : IRegionModule, IDynamicTextureRender - { - private string m_name = "LoadImageURL"; - private IDynamicTextureManager m_textureManager; - private Scene m_scene; - - 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; } - } - - 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(LLUUID id, string url, string extraParams) - { - MakeHttpRequest(url, id); - return true; - } - - public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) - { - return false; - } - - private void MakeHttpRequest(string url, LLUUID requestID) - { - WebRequest request = HttpWebRequest.Create(url); - RequestState state = new RequestState((HttpWebRequest) request, requestID); - IAsyncResult result = 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; - 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 = OpenJPEG.EncodeFromImage(resize, true); - - m_textureManager.ReturnData(state.RequestID, imageJ2000); - } - } - - public class RequestState - { - public HttpWebRequest Request = null; - public LLUUID RequestID = LLUUID.Zero; - public int TimeOfRequest = 0; - - public RequestState(HttpWebRequest request, LLUUID requestID) - { - Request = request; - RequestID = requestID; - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using Nini.Config; +using OpenJPEGNet; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Scripting.LoadImageURL +{ + public class LoadImageURLModule : IRegionModule, IDynamicTextureRender + { + private string m_name = "LoadImageURL"; + private IDynamicTextureManager m_textureManager; + private Scene m_scene; + + 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; } + } + + 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(LLUUID id, string url, string extraParams) + { + MakeHttpRequest(url, id); + return true; + } + + public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) + { + return false; + } + + private void MakeHttpRequest(string url, LLUUID requestID) + { + WebRequest request = HttpWebRequest.Create(url); + RequestState state = new RequestState((HttpWebRequest) request, requestID); + IAsyncResult result = 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; + 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 = OpenJPEG.EncodeFromImage(resize, true); + + m_textureManager.ReturnData(state.RequestID, imageJ2000); + } + } + + public class RequestState + { + public HttpWebRequest Request = null; + public LLUUID RequestID = LLUUID.Zero; + public int TimeOfRequest = 0; + + public RequestState(HttpWebRequest request, LLUUID requestID) + { + Request = request; + RequestID = requestID; + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/VectorRenderModule.cs b/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs similarity index 96% rename from OpenSim/Region/Environment/Modules/VectorRenderModule.cs rename to OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs index 0ea6fc36e2..4fba5b9534 100644 --- a/OpenSim/Region/Environment/Modules/VectorRenderModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs @@ -1,361 +1,361 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using Nini.Config; -using OpenJPEGNet; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using Image=System.Drawing.Image; - -//using Cairo; - -namespace OpenSim.Region.Environment.Modules -{ - public class VectorRenderModule : IRegionModule, IDynamicTextureRender - { - private Scene m_scene; - private string m_name = "VectorRenderModule"; - private IDynamicTextureManager m_textureManager; - - public VectorRenderModule() - { - } - - 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; } - } - - private void Draw(string data, LLUUID id, string extraParams) - { - // TODO: this is a brutal hack. extraParams should actually be parsed reasonably. - int size = 256; - try { - size = Convert.ToInt32(extraParams); - } catch (Exception e) { - -//Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used - Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString()); - } - - if ((size < 128) || (size > 1024)) - size = 256; - - Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb); - - Graphics graph = Graphics.FromImage(bitmap); - - extraParams = extraParams.ToLower(); - int alpha = 255; - if (extraParams == "setalpha") - { - alpha = 0; - } - else - { - graph.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size); - } - - 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 = OpenJPEG.EncodeFromImage(bitmap, true); - m_textureManager.ReturnData(id, imageJ2000); - - } - -/* - 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); - Font myFont = new Font("Times New Roman", 14); - 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(); - float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - myFont = new Font("Times New Roman", size); - } - else if (nextLine.StartsWith("PenSize")) - { - nextLine = nextLine.Remove(0, 8); - 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(); - - Color 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; - } - - 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(LLUUID id, string url, string extraParams) - { - return false; - } - - public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) - { - Draw(bodyData, id, extraParams); - return true; - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using Nini.Config; +using OpenJPEGNet; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using Image=System.Drawing.Image; + +//using Cairo; + +namespace OpenSim.Region.Environment.Modules.Scripting.VectorRender +{ + public class VectorRenderModule : IRegionModule, IDynamicTextureRender + { + private Scene m_scene; + private string m_name = "VectorRenderModule"; + private IDynamicTextureManager m_textureManager; + + public VectorRenderModule() + { + } + + 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; } + } + + private void Draw(string data, LLUUID id, string extraParams) + { + // TODO: this is a brutal hack. extraParams should actually be parsed reasonably. + int size = 256; + try { + size = Convert.ToInt32(extraParams); + } catch (Exception e) { + +//Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used + Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString()); + } + + if ((size < 128) || (size > 1024)) + size = 256; + + Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb); + + Graphics graph = Graphics.FromImage(bitmap); + + extraParams = extraParams.ToLower(); + int alpha = 255; + if (extraParams == "setalpha") + { + alpha = 0; + } + else + { + graph.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size); + } + + 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 = OpenJPEG.EncodeFromImage(bitmap, true); + m_textureManager.ReturnData(id, imageJ2000); + + } + +/* + 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); + Font myFont = new Font("Times New Roman", 14); + 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(); + float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); + myFont = new Font("Times New Roman", size); + } + else if (nextLine.StartsWith("PenSize")) + { + nextLine = nextLine.Remove(0, 8); + 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(); + + Color 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; + } + + 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(LLUUID id, string url, string extraParams) + { + return false; + } + + public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) + { + Draw(bodyData, id, extraParams); + return true; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs similarity index 91% rename from OpenSim/Region/Environment/Modules/WorldCommModule.cs rename to OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs index 638deed71a..a949fb6ab7 100644 --- a/OpenSim/Region/Environment/Modules/WorldCommModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs @@ -1,584 +1,578 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -/***************************************************** - * - * 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. - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules -{ - public class WorldCommModule : IRegionModule, IWorldComm - { - private Scene m_scene; - private object CommListLock = new object(); - private object ListLock = new object(); - private string m_name = "WorldCommModule"; - private ListenerManager m_listenerManager; - private Queue m_pendingQ; - private Queue m_pending; - - public WorldCommModule() - { - } - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - m_listenerManager = new ListenerManager(); - m_scene.EventManager.OnNewClient += NewClient; - m_pendingQ = new Queue(); - m_pending = Queue.Synchronized(m_pendingQ); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void NewClient(IClientAPI client) - { - client.OnChatFromViewer += DeliverClientMessage; - } - - /******************************************************************** - * - * Listener Stuff - * - * *****************************************************************/ - private void DeliverClientMessage(Object sender, ChatFromViewerArgs e) - { - DeliverMessage(e.Sender.AgentId.ToString(), - e.Type, e.Channel, - e.Sender.FirstName + " " + e.Sender.LastName, - e.Message); - } - - public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) - { - return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); - } - - public void ListenControl(int handle, int active) - { - if (m_listenerManager != null) - { - if (active == 1) - m_listenerManager.Activate(handle); - else if (active == 0) - m_listenerManager.Dectivate(handle); - } - } - - public void ListenRemove(int handle) - { - if (m_listenerManager != null) - { - m_listenerManager.Remove(handle); - } - } - - public void DeleteListener(LLUUID itemID) - { - if (m_listenerManager != null) - { - m_listenerManager.DeleteListener(itemID); - } - } - - // This method scans nearby objects and determines if they are listeners, - // and if so if this message fits the filter. If it does, then - // enqueue the message for delivery to the objects listen event handler. - // Objects that do an llSay have their messages delivered here, and for - // nearby avatars, the SimChat function is used. - public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg) - { - SceneObjectPart source = null; - ScenePresence avatar = null; - - source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID)); - if (source == null) - { - avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID)); - } - if ((avatar != null) || (source != null)) - { - // Loop through the objects in the scene - // If they are in proximity, then if they are - // listeners, if so add them to the pending queue - - foreach (ListenerInfo li in m_listenerManager.GetListeners()) - { - EntityBase sPart; - - m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); - - if (sPart != null) - { - double dis = 0; - - if (source != null) - dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); - else - dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); - - switch (type) - { - case ChatTypeEnum.Whisper: - - if ((dis < 10) && (dis > -10)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Say: - - if ((dis < 30) && (dis > -30)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Shout: - if ((dis < 100) && (dis > -100)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Broadcast: - // Dont process if this message is from itself! - if (li.GetHostID().ToString().Equals(sourceItemID) || - sPart.UUID.ToString().Equals(sourceItemID)) - continue; - - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - - break; - } - } - } - } - } - - public bool HasMessages() - { - if (m_pending != null) - return (m_pending.Count > 0); - else - return false; - } - - public ListenerInfo GetNextMessage() - { - ListenerInfo li = null; - - lock (m_pending.SyncRoot) - { - li = (ListenerInfo)m_pending.Dequeue(); - } - - return li; - } - - public uint PeekNextMessageLocalID() - { - return ((ListenerInfo)m_pending.Peek()).GetLocalID(); - } - - public LLUUID PeekNextMessageItemID() - { - return ((ListenerInfo)m_pending.Peek()).GetItemID(); - } - } - - /********************************************************** - * - * Even more listener stuff - * - * ********************************************************/ - public class ListenerManager - { - //private Dictionary m_listeners; - private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable()); - private object ListenersLock = new object(); - private int m_MaxListeners = 100; - - public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) - { - if (m_listeners.Count < m_MaxListeners) - { - ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg); - - if (isListener == null) - { - int newHandle = GetNewHandle(); - - if (newHandle > -1) - { - ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); - - lock (m_listeners.SyncRoot) - { - m_listeners.Add(newHandle, li); - } - - return newHandle; - } - } - } - - return -1; - } - - public void Remove(int handle) - { - lock (m_listeners.SyncRoot) - { - m_listeners.Remove(handle); - } - } - - public void DeleteListener(LLUUID itemID) - { - ArrayList removedListeners = new ArrayList(); - - lock (m_listeners.SyncRoot) - { - IDictionaryEnumerator en = m_listeners.GetEnumerator(); - while (en.MoveNext()) - { - ListenerInfo li = (ListenerInfo)en.Value; - if (li.GetItemID().Equals(itemID)) - { - removedListeners.Add(li.GetHandle()); - } - } - foreach (int handle in removedListeners) - { - m_listeners.Remove(handle); - } - } - } - - private int GetNewHandle() - { - for (int i = 0; i < int.MaxValue - 1; i++) - { - if (!m_listeners.ContainsKey(i)) - return i; - } - - return -1; - } - - public bool IsListener(LLUUID hostID) - { - foreach (ListenerInfo li in m_listeners.Values) - { - if (li.GetHostID().Equals(hostID)) - return true; - } - - return false; - } - - public void Activate(int handle) - { - - if (m_listeners.ContainsKey(handle)) - { - lock (m_listeners.SyncRoot) - { - ListenerInfo li = (ListenerInfo)m_listeners[handle]; - li.Activate(); - } - } - } - - public void Dectivate(int handle) - { - - if (m_listeners.ContainsKey(handle)) - { - ListenerInfo li = (ListenerInfo)m_listeners[handle]; - li.Deactivate(); - } - } - - // Theres probably a more clever and efficient way to - // do this, maybe with regex. - public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, - string msg) - { - bool isMatch = true; - lock (m_listeners.SyncRoot) - { - IDictionaryEnumerator en = m_listeners.GetEnumerator(); - while (en.MoveNext()) - { - ListenerInfo li = (ListenerInfo)en.Value; - - if (li.IsActive()) - { - if (li.GetHostID().Equals(listenerKey)) - { - if (channel == li.GetChannel()) - { - if ((li.GetID().ToString().Length > 0) && - (!li.GetID().Equals(LLUUID.Zero))) - { - if (!li.GetID().ToString().Equals(sourceItemID)) - { - isMatch = false; - } - } - if (isMatch && (li.GetName().Length > 0)) - { - if (li.GetName().Equals(name)) - { - isMatch = false; - } - } - if (isMatch) - { - return new ListenerInfo( - li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), - li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) - ); - } - } - } - } - } - } - return null; - } - - public ICollection GetListeners() - { - return m_listeners.Values; - } - } - - public class ListenerInfo - { - private LLUUID m_itemID; // ID of the host script engine - private LLUUID m_hostID; // ID of the host/scene part - private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message - private int m_channel; // Channel - private int m_handle; // Assigned handle of this listener - private uint m_localID; // Local ID from script engine - private string m_name; // Object name to filter messages from - private LLUUID m_id; // ID to filter messages from - private string m_message; // The message - private bool m_active; // Listener is active or not - - public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message) - { - Initialise(localID, handle, ItemID, hostID, channel, name, id, message); - } - - public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, - string message, LLUUID sourceItemID) - { - Initialise(localID, handle, ItemID, hostID, channel, name, id, message); - m_sourceItemID = sourceItemID; - } - - private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, - LLUUID id, string message) - { - m_handle = handle; - m_channel = channel; - m_itemID = ItemID; - m_hostID = hostID; - m_name = name; - m_id = id; - m_message = message; - m_active = true; - m_localID = localID; - } - - public LLUUID GetItemID() - { - return m_itemID; - } - - public LLUUID GetHostID() - { - return m_hostID; - } - - public LLUUID GetSourceItemID() - { - return m_sourceItemID; - } - - 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 LLUUID GetID() - { - return m_id; - } - } - -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * 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. + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm +{ + public class WorldCommModule : IRegionModule, IWorldComm + { + private Scene m_scene; + private object CommListLock = new object(); + private object ListLock = new object(); + private string m_name = "WorldCommModule"; + private ListenerManager m_listenerManager; + private Queue m_pendingQ; + private Queue m_pending; + + public WorldCommModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_listenerManager = new ListenerManager(); + m_scene.EventManager.OnNewClient += NewClient; + m_pendingQ = new Queue(); + m_pending = Queue.Synchronized(m_pendingQ); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnChatFromViewer += DeliverClientMessage; + } + + /******************************************************************** + * + * Listener Stuff + * + * *****************************************************************/ + private void DeliverClientMessage(Object sender, ChatFromViewerArgs e) + { + DeliverMessage(e.Sender.AgentId.ToString(), + e.Type, e.Channel, + e.Sender.FirstName + " " + e.Sender.LastName, + e.Message); + } + + public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) + { + return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); + } + + public void ListenControl(int handle, int active) + { + if (m_listenerManager != null) + { + if (active == 1) + m_listenerManager.Activate(handle); + else if (active == 0) + m_listenerManager.Dectivate(handle); + } + } + + public void ListenRemove(int handle) + { + if (m_listenerManager != null) + { + m_listenerManager.Remove(handle); + } + } + + public void DeleteListener(LLUUID itemID) + { + if (m_listenerManager != null) + { + m_listenerManager.DeleteListener(itemID); + } + } + + // This method scans nearby objects and determines if they are listeners, + // and if so if this message fits the filter. If it does, then + // enqueue the message for delivery to the objects listen event handler. + // Objects that do an llSay have their messages delivered here, and for + // nearby avatars, the SimChat function is used. + public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg) + { + SceneObjectPart source = null; + ScenePresence avatar = null; + + source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID)); + if (source == null) + { + avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID)); + } + if ((avatar != null) || (source != null)) + { + // Loop through the objects in the scene + // If they are in proximity, then if they are + // listeners, if so add them to the pending queue + + foreach (ListenerInfo li in m_listenerManager.GetListeners()) + { + EntityBase sPart; + + m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); + + if (sPart != null) + { + double dis = 0; + + if (source != null) + dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); + else + dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); + + switch (type) + { + case ChatTypeEnum.Whisper: + + if ((dis < 10) && (dis > -10)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Say: + + if ((dis < 30) && (dis > -30)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Shout: + if ((dis < 100) && (dis > -100)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Broadcast: + // Dont process if this message is from itself! + if (li.GetHostID().ToString().Equals(sourceItemID) || + sPart.UUID.ToString().Equals(sourceItemID)) + continue; + + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + + break; + } + } + } + } + } + + public bool HasMessages() + { + if (m_pending != null) + return (m_pending.Count > 0); + else + return false; + } + + public ListenerInfo GetNextMessage() + { + ListenerInfo li = null; + + lock (m_pending.SyncRoot) + { + li = (ListenerInfo)m_pending.Dequeue(); + } + + return li; + } + + public uint PeekNextMessageLocalID() + { + return ((ListenerInfo)m_pending.Peek()).GetLocalID(); + } + + public LLUUID PeekNextMessageItemID() + { + return ((ListenerInfo)m_pending.Peek()).GetItemID(); + } + } + + public class ListenerManager + { + //private Dictionary m_listeners; + private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable()); + private object ListenersLock = new object(); + private int m_MaxListeners = 100; + + public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) + { + if (m_listeners.Count < m_MaxListeners) + { + ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg); + + if (isListener == null) + { + int newHandle = GetNewHandle(); + + if (newHandle > -1) + { + ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); + + lock (m_listeners.SyncRoot) + { + m_listeners.Add(newHandle, li); + } + + return newHandle; + } + } + } + + return -1; + } + + public void Remove(int handle) + { + lock (m_listeners.SyncRoot) + { + m_listeners.Remove(handle); + } + } + + public void DeleteListener(LLUUID itemID) + { + ArrayList removedListeners = new ArrayList(); + + lock (m_listeners.SyncRoot) + { + IDictionaryEnumerator en = m_listeners.GetEnumerator(); + while (en.MoveNext()) + { + ListenerInfo li = (ListenerInfo)en.Value; + if (li.GetItemID().Equals(itemID)) + { + removedListeners.Add(li.GetHandle()); + } + } + foreach (int handle in removedListeners) + { + m_listeners.Remove(handle); + } + } + } + + private int GetNewHandle() + { + for (int i = 0; i < int.MaxValue - 1; i++) + { + if (!m_listeners.ContainsKey(i)) + return i; + } + + return -1; + } + + public bool IsListener(LLUUID hostID) + { + foreach (ListenerInfo li in m_listeners.Values) + { + if (li.GetHostID().Equals(hostID)) + return true; + } + + return false; + } + + public void Activate(int handle) + { + + if (m_listeners.ContainsKey(handle)) + { + lock (m_listeners.SyncRoot) + { + ListenerInfo li = (ListenerInfo)m_listeners[handle]; + li.Activate(); + } + } + } + + public void Dectivate(int handle) + { + + if (m_listeners.ContainsKey(handle)) + { + ListenerInfo li = (ListenerInfo)m_listeners[handle]; + li.Deactivate(); + } + } + + // Theres probably a more clever and efficient way to + // do this, maybe with regex. + public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, + string msg) + { + bool isMatch = true; + lock (m_listeners.SyncRoot) + { + IDictionaryEnumerator en = m_listeners.GetEnumerator(); + while (en.MoveNext()) + { + ListenerInfo li = (ListenerInfo)en.Value; + + if (li.IsActive()) + { + if (li.GetHostID().Equals(listenerKey)) + { + if (channel == li.GetChannel()) + { + if ((li.GetID().ToString().Length > 0) && + (!li.GetID().Equals(LLUUID.Zero))) + { + if (!li.GetID().ToString().Equals(sourceItemID)) + { + isMatch = false; + } + } + if (isMatch && (li.GetName().Length > 0)) + { + if (li.GetName().Equals(name)) + { + isMatch = false; + } + } + if (isMatch) + { + return new ListenerInfo( + li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), + li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) + ); + } + } + } + } + } + } + return null; + } + + public ICollection GetListeners() + { + return m_listeners.Values; + } + } + + public class ListenerInfo + { + private LLUUID m_itemID; // ID of the host script engine + private LLUUID m_hostID; // ID of the host/scene part + private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message + private int m_channel; // Channel + private int m_handle; // Assigned handle of this listener + private uint m_localID; // Local ID from script engine + private string m_name; // Object name to filter messages from + private LLUUID m_id; // ID to filter messages from + private string m_message; // The message + private bool m_active; // Listener is active or not + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + } + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, + string message, LLUUID sourceItemID) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + m_sourceItemID = sourceItemID; + } + + private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, + LLUUID id, string message) + { + m_handle = handle; + m_channel = channel; + m_itemID = ItemID; + m_hostID = hostID; + m_name = name; + m_id = id; + m_message = message; + m_active = true; + m_localID = localID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetHostID() + { + return m_hostID; + } + + public LLUUID GetSourceItemID() + { + return m_sourceItemID; + } + + 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 LLUUID GetID() + { + return m_id; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs similarity index 96% rename from OpenSim/Region/Environment/Modules/XMLRPCModule.cs rename to OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs index e915fb8fd4..1139b4b8ae 100644 --- a/OpenSim/Region/Environment/Modules/XMLRPCModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs @@ -1,680 +1,672 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 libsecondlife; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.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 -{ - public class XMLRPCModule : IRegionModule, IXMLRPC - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private object XMLRPCListLock = new object(); - private string m_name = "XMLRPCModule"; - private int RemoteReplyScriptWait = 300; - private int RemoteReplyScriptTimeout = 9000; - private int m_remoteDataPort = 0; - private List m_scenes = new List(); - - // - private Dictionary m_openChannels; - - private Dictionary m_rpcPending; - private Dictionary m_rpcPendingResponses; - - private Dictionary m_pendingSRDResponses; - - public void Initialise(Scene scene, IConfigSource config) - { - 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()) - { - m_openChannels = new Dictionary(); - m_rpcPending = new Dictionary(); - m_rpcPendingResponses = new Dictionary(); - m_pendingSRDResponses = new Dictionary(); - - // 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; } - } - - public bool IsEnabled() - { - return (m_remoteDataPort > 0); - } - - /********************************************** - * OpenXMLRPCChannel - * - * Generate a LLUUID channel key and add it and - * the prim id to dictionary - * - * 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 LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID) - { - LLUUID channel = new LLUUID(); - - //Is a dupe? - foreach (RPCChannelInfo ci in m_openChannels.Values) - { - if (ci.GetItemID().Equals(itemID)) - { - // return the original channel ID for this item - channel = ci.GetChannelID(); - break; - } - } - - if (channel == LLUUID.Zero) - { - channel = LLUUID.Random(); - RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel); - lock (XMLRPCListLock) - { - m_openChannels.Add(channel, rpcChanInfo); - } - } - - return channel; - } - - // Delete channels based on itemID - // for when a script is deleted - public void DeleteChannels(LLUUID 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((LLUUID)tmpEnumerator.Current); - } - - } - - } - - /********************************************** - * Remote Data Reply - * - * Response to RPC message - * - *********************************************/ - - public void RemoteDataReply(string channel, string message_id, string sdata, int idata) - { - RPCRequestInfo rpcInfo; - LLUUID message_key = new LLUUID(message_id); - - if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo)) - { - rpcInfo.SetStrRetval(sdata); - rpcInfo.SetIntRetval(idata); - rpcInfo.SetProcessed(true); - m_rpcPendingResponses.Remove(message_key); - } - } - - /********************************************** - * CloseXMLRPCChannel - * - * Remove channel from dictionary - * - *********************************************/ - - public void CloseXMLRPCChannel(LLUUID channelKey) - { - if (m_openChannels.ContainsKey(channelKey)) - m_openChannels.Remove(channelKey); - } - - - 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) - { - LLUUID channel = new LLUUID((string)requestData["Channel"]); - RPCChannelInfo rpcChanInfo; - if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) - { - string intVal = (string)requestData["IntValue"]; - 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"] = Convert.ToString(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 bool hasRequests() - { - lock (XMLRPCListLock) - { - if (m_rpcPending != null) - return (m_rpcPending.Count > 0); - else - return false; - } - } - - public RPCRequestInfo GetNextCompletedRequest() - { - if (m_rpcPending != null) - { - lock (XMLRPCListLock) - { - foreach (LLUUID luid in m_rpcPending.Keys) - { - RPCRequestInfo tmpReq; - - if (m_rpcPending.TryGetValue(luid, out tmpReq)) - { - - if (!tmpReq.IsProcessed()) return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedRequest(LLUUID 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 LLUUID SendRemoteData(uint localID, LLUUID 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); - return req.process(); - - } - - public SendRemoteDataRequest GetNextCompletedSRDRequest() - { - if (m_pendingSRDResponses != null) - { - lock (XMLRPCListLock) - { - foreach (LLUUID luid in m_pendingSRDResponses.Keys) - { - SendRemoteDataRequest tmpReq; - - if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq)) - { - if (tmpReq.finished) - return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedSRDRequest(LLUUID id) - { - lock (XMLRPCListLock) - { - SendRemoteDataRequest tmpReq; - if (m_pendingSRDResponses.TryGetValue(id, out tmpReq)) - { - m_pendingSRDResponses.Remove(id); - } - } - } - - public void CancelSRDRequests(LLUUID itemID) - { - if (m_pendingSRDResponses != null) - { - lock (XMLRPCListLock) - { - foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values) - { - if (li.m_itemID.Equals(itemID)) - m_pendingSRDResponses.Remove(li.GetReqID()); - } - } - } - } - } - - /************************************************************** - * - * Class RPCRequestInfo - * - * Holds details about incoming requests until they are picked - * from the queue by LSLLongCmdHandler - * ***********************************************************/ - - public class RPCRequestInfo - { - private string m_StrVal; - private string m_IntVal; - private bool m_processed; - private string m_respStr; - private int m_respInt; - private uint m_localID; - private LLUUID m_ItemID; - private LLUUID m_MessageID; - private LLUUID m_ChannelKey; - - public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal) - { - m_localID = localID; - m_StrVal = strVal; - m_IntVal = intVal; - m_ItemID = itemID; - m_ChannelKey = channelKey; - m_MessageID = LLUUID.Random(); - m_processed = false; - m_respStr = String.Empty; - m_respInt = 0; - } - - public bool IsProcessed() - { - return m_processed; - } - - public LLUUID 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 LLUUID GetItemID() - { - return m_ItemID; - } - - public string GetStrVal() - { - return m_StrVal; - } - - public int GetIntValue() - { - return int.Parse(m_IntVal); - } - - public LLUUID GetMessageID() - { - return m_MessageID; - } - } - - public class RPCChannelInfo - { - private LLUUID m_itemID; - private uint m_localID; - private LLUUID m_ChannelKey; - - public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID) - { - m_ChannelKey = channelID; - m_localID = localID; - m_itemID = itemID; - } - - public LLUUID GetItemID() - { - return m_itemID; - } - - public LLUUID GetChannelID() - { - return m_ChannelKey; - } - - public uint GetLocalID() - { - return m_localID; - } - - } - - public class SendRemoteDataRequest - { - - public LLUUID reqID; - public string destURL; - public string channel; - public string sdata; - public int idata; - public bool finished; - public string response_sdata; - public int response_idata; - public XmlRpcRequest request; - private Thread httpThread; - public LLUUID m_itemID; - public uint m_localID; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) - { - - this.channel = channel; - this.destURL = dest; - this.idata = idata; - this.sdata = sdata; - m_itemID = itemID; - m_localID = localID; - - reqID = LLUUID.Random(); - - } - - public LLUUID process() - { - httpThread = new Thread(SendRequest); - httpThread.Name = "HttpRequestThread"; - httpThread.Priority = ThreadPriority.BelowNormal; - httpThread.IsBackground = true; - finished = false; - httpThread.Start(); - ThreadTracker.Add(httpThread); - - return reqID; - - } - - /* - * 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 LLUUID - // if not, use as method name - LLUUID parseUID; - string mName = "llRemoteData"; - if( (channel != null) && (channel != "") ) - if( !LLUUID.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(Type.GetType("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 (WebException 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 LLUUID GetReqID() - { - return reqID; - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 libsecondlife; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.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 object XMLRPCListLock = new object(); + private string m_name = "XMLRPCModule"; + private int RemoteReplyScriptWait = 300; + private int RemoteReplyScriptTimeout = 9000; + private int m_remoteDataPort = 0; + private List m_scenes = new List(); + + // + private Dictionary m_openChannels; + + private Dictionary m_rpcPending; + private Dictionary m_rpcPendingResponses; + + private Dictionary m_pendingSRDResponses; + + public void Initialise(Scene scene, IConfigSource config) + { + 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()) + { + m_openChannels = new Dictionary(); + m_rpcPending = new Dictionary(); + m_rpcPendingResponses = new Dictionary(); + m_pendingSRDResponses = new Dictionary(); + + // 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; } + } + + public bool IsEnabled() + { + return (m_remoteDataPort > 0); + } + + /********************************************** + * OpenXMLRPCChannel + * + * Generate a LLUUID channel key and add it and + * the prim id to dictionary + * + * 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 LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID) + { + LLUUID channel = new LLUUID(); + + //Is a dupe? + foreach (RPCChannelInfo ci in m_openChannels.Values) + { + if (ci.GetItemID().Equals(itemID)) + { + // return the original channel ID for this item + channel = ci.GetChannelID(); + break; + } + } + + if (channel == LLUUID.Zero) + { + channel = LLUUID.Random(); + RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel); + lock (XMLRPCListLock) + { + m_openChannels.Add(channel, rpcChanInfo); + } + } + + return channel; + } + + // Delete channels based on itemID + // for when a script is deleted + public void DeleteChannels(LLUUID 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((LLUUID)tmpEnumerator.Current); + } + + } + + } + + /********************************************** + * Remote Data Reply + * + * Response to RPC message + * + *********************************************/ + + public void RemoteDataReply(string channel, string message_id, string sdata, int idata) + { + RPCRequestInfo rpcInfo; + LLUUID message_key = new LLUUID(message_id); + + if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo)) + { + rpcInfo.SetStrRetval(sdata); + rpcInfo.SetIntRetval(idata); + rpcInfo.SetProcessed(true); + m_rpcPendingResponses.Remove(message_key); + } + } + + /********************************************** + * CloseXMLRPCChannel + * + * Remove channel from dictionary + * + *********************************************/ + + public void CloseXMLRPCChannel(LLUUID channelKey) + { + if (m_openChannels.ContainsKey(channelKey)) + m_openChannels.Remove(channelKey); + } + + + 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) + { + LLUUID channel = new LLUUID((string)requestData["Channel"]); + RPCChannelInfo rpcChanInfo; + if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) + { + string intVal = (string)requestData["IntValue"]; + 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"] = Convert.ToString(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 bool hasRequests() + { + lock (XMLRPCListLock) + { + if (m_rpcPending != null) + return (m_rpcPending.Count > 0); + else + return false; + } + } + + public RPCRequestInfo GetNextCompletedRequest() + { + if (m_rpcPending != null) + { + lock (XMLRPCListLock) + { + foreach (LLUUID luid in m_rpcPending.Keys) + { + RPCRequestInfo tmpReq; + + if (m_rpcPending.TryGetValue(luid, out tmpReq)) + { + + if (!tmpReq.IsProcessed()) return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedRequest(LLUUID 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 LLUUID SendRemoteData(uint localID, LLUUID 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); + return req.process(); + + } + + public SendRemoteDataRequest GetNextCompletedSRDRequest() + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (LLUUID luid in m_pendingSRDResponses.Keys) + { + SendRemoteDataRequest tmpReq; + + if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.finished) + return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedSRDRequest(LLUUID id) + { + lock (XMLRPCListLock) + { + SendRemoteDataRequest tmpReq; + if (m_pendingSRDResponses.TryGetValue(id, out tmpReq)) + { + m_pendingSRDResponses.Remove(id); + } + } + } + + public void CancelSRDRequests(LLUUID itemID) + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values) + { + if (li.m_itemID.Equals(itemID)) + m_pendingSRDResponses.Remove(li.GetReqID()); + } + } + } + } + } + + public class RPCRequestInfo + { + private string m_StrVal; + private string m_IntVal; + private bool m_processed; + private string m_respStr; + private int m_respInt; + private uint m_localID; + private LLUUID m_ItemID; + private LLUUID m_MessageID; + private LLUUID m_ChannelKey; + + public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal) + { + m_localID = localID; + m_StrVal = strVal; + m_IntVal = intVal; + m_ItemID = itemID; + m_ChannelKey = channelKey; + m_MessageID = LLUUID.Random(); + m_processed = false; + m_respStr = String.Empty; + m_respInt = 0; + } + + public bool IsProcessed() + { + return m_processed; + } + + public LLUUID 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 LLUUID GetItemID() + { + return m_ItemID; + } + + public string GetStrVal() + { + return m_StrVal; + } + + public int GetIntValue() + { + return int.Parse(m_IntVal); + } + + public LLUUID GetMessageID() + { + return m_MessageID; + } + } + + public class RPCChannelInfo + { + private LLUUID m_itemID; + private uint m_localID; + private LLUUID m_ChannelKey; + + public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID) + { + m_ChannelKey = channelID; + m_localID = localID; + m_itemID = itemID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetChannelID() + { + return m_ChannelKey; + } + + public uint GetLocalID() + { + return m_localID; + } + + } + + public class SendRemoteDataRequest + { + + public LLUUID reqID; + public string destURL; + public string channel; + public string sdata; + public int idata; + public bool finished; + public string response_sdata; + public int response_idata; + public XmlRpcRequest request; + private Thread httpThread; + public LLUUID m_itemID; + public uint m_localID; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) + { + + this.channel = channel; + this.destURL = dest; + this.idata = idata; + this.sdata = sdata; + m_itemID = itemID; + m_localID = localID; + + reqID = LLUUID.Random(); + + } + + public LLUUID process() + { + httpThread = new Thread(SendRequest); + httpThread.Name = "HttpRequestThread"; + httpThread.Priority = ThreadPriority.BelowNormal; + httpThread.IsBackground = true; + finished = false; + httpThread.Start(); + ThreadTracker.Add(httpThread); + + return reqID; + + } + + /* + * 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 LLUUID + // if not, use as method name + LLUUID parseUID; + string mName = "llRemoteData"; + if( (channel != null) && (channel != "") ) + if( !LLUUID.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(Type.GetType("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 (WebException 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 LLUUID GetReqID() + { + return reqID; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/SunModule.cs b/OpenSim/Region/Environment/Modules/SunModule.cs deleted file mode 100644 index e6801e8cd3..0000000000 --- a/OpenSim/Region/Environment/Modules/SunModule.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.Collections.Generic; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.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 m_real_day = 24.0; - private const int m_default_frame = 100; - private int m_frame_mod; - private double m_day_length; - private int m_dilation; - private int m_frame; - private long m_start; - - private Scene m_scene; - - public void Initialise(Scene scene, IConfigSource config) - { - m_start = DateTime.Now.Ticks; - m_frame = 0; - - // Just in case they don't have the stanzas - try - { - m_day_length = config.Configs["Sun"].GetDouble("day_length", m_real_day); - m_frame_mod = config.Configs["Sun"].GetInt("frame_rate", m_default_frame); - } - catch (Exception) - { - m_day_length = m_real_day; - m_frame_mod = m_default_frame; - } - - m_dilation = (int) (m_real_day/m_day_length); - m_scene = scene; - scene.EventManager.OnFrame += SunUpdate; - scene.EventManager.OnNewClient += SunToClient; - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "SunModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void SunToClient(IClientAPI client) - { - client.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); - } - - public void SunUpdate() - { - if (m_frame < m_frame_mod) - { - m_frame++; - return; - } - // m_log.InfoFormat("[SUN]: I've got an update {0} => {1}", m_scene.RegionsInfo.RegionName, HourOfTheDay()); - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence avatar in avatars) - { - avatar.ControllingClient.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); - } - // set estate settings for region access to sun position - m_scene.RegionInfo.EstateSettings.sunPosition = SunPos(HourOfTheDay()); - - m_frame = 0; - } - - // Hour of the Day figures out the hour of the day as a float. - // The intent here is that we seed hour of the day with real - // time when the simulator starts, then run time forward - // faster based on time dilation factor. This means that - // ticks don't get out of hand - private double HourOfTheDay() - { - long m_addticks = (DateTime.Now.Ticks - m_start)*m_dilation; - DateTime dt = new DateTime(m_start + m_addticks); - return (double) dt.Hour + ((double) dt.Minute/60.0); - } - - private LLVector3 SunPos(double hour) - { - // now we have our radian position - double rad = (hour/m_real_day)*2*Math.PI - (Math.PI/2.0); - double z = Math.Sin(rad); - double x = Math.Cos(rad); - return new LLVector3((float) x, 0f, (float) z); - } - - // TODO: clear this out. This is here so that I remember to - // figure out if we need those other packet fields that I've - // left out so far - // - // public void SendViewerTime(int phase) - // { - // Console.WriteLine("SunPhase: {0}", phase); - // SimulatorViewerTimeMessagePacket viewertime = new SimulatorViewerTimeMessagePacket(); - // //viewertime.TimeInfo.SecPerDay = 86400; - // // viewertime.TimeInfo.SecPerYear = 31536000; - // viewertime.TimeInfo.SecPerDay = 1000; - // viewertime.TimeInfo.SecPerYear = 365000; - // viewertime.TimeInfo.SunPhase = 1; - // int sunPhase = (phase + 2)/2; - // if ((sunPhase < 6) || (sunPhase > 36)) - // { - // viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f); - // Console.WriteLine("sending night"); - // } - // else - // { - // if (sunPhase < 12) - // { - // sunPhase = 12; - // } - // sunPhase = sunPhase - 12; - // - // float yValue = 0.1f*(sunPhase); - // Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue); - // if (yValue > 1.2f) - // { - // yValue = yValue - 1.2f; - // } - // if (yValue > 1) - // { - // yValue = 1; - // } - // if (yValue < 0) - // { - // yValue = 0; - // } - // if (sunPhase < 14) - // { - // yValue = 1 - yValue; - // } - // if (sunPhase < 12) - // { - // yValue *= -1; - // } - // viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f); - // Console.WriteLine("sending sun update " + yValue); - // } - // viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f); - // viewertime.TimeInfo.UsecSinceStart = (ulong) Util.UnixTimeSinceEpoch(); - // // OutPacket(viewertime); - // } - } -} diff --git a/OpenSim/Region/Environment/Modules/TeleportModule.cs b/OpenSim/Region/Environment/Modules/TeleportModule.cs deleted file mode 100644 index 9a90377b7c..0000000000 --- a/OpenSim/Region/Environment/Modules/TeleportModule.cs +++ /dev/null @@ -1,33 +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. - */ - -namespace OpenSim.Region.Environment.Modules -{ - internal class TeleportModule - { - } -} diff --git a/OpenSim/Region/Environment/Modules/Terrain/Effects/CookieCutter.cs b/OpenSim/Region/Environment/Modules/Terrain/Effects/CookieCutter.cs deleted file mode 100644 index 6d41ebad5c..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/Effects/CookieCutter.cs +++ /dev/null @@ -1,124 +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.Environment.Interfaces; -using OpenSim.Region.Environment.Modules.Terrain.FloodBrushes; -using OpenSim.Region.Environment.Modules.Terrain.PaintBrushes; - -namespace OpenSim.Region.Environment.Modules.Terrain.Effects -{ - internal class CookieCutter : ITerrainEffect - { - #region ITerrainEffect Members - - public void RunEffect(ITerrainChannel map) - { - SmoothArea smooth = new SmoothArea(); - 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]; - - 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; - - // 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; - - int channelsX = 4; - int channelWidth = (map.Width / channelsX / 4); - 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] == true) - eroder.PaintEffect(map, x, y, 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; - } - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/Environment/Modules/Terrain/Effects/DefaultTerrainGenerator.cs deleted file mode 100644 index 2327275aed..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/Effects/DefaultTerrainGenerator.cs +++ /dev/null @@ -1,55 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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/Terrain/FileLoaders/BMP.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/BMP.cs deleted file mode 100644 index f975872ee1..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/BMP.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.Drawing; -using System.Drawing.Imaging; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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); - } - - /// - /// The human readable version of the file format(s) this loader handles - /// - /// - public override string ToString() - { - return "BMP"; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GIF.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GIF.cs deleted file mode 100644 index cf82000419..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GIF.cs +++ /dev/null @@ -1,47 +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 OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders -{ - internal class GIF : GenericSystemDrawing - { - public override void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Gif); - } - - public override string ToString() - { - return "GIF"; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GenericSystemDrawing.cs deleted file mode 100644 index b05c1cd660..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/GenericSystemDrawing.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.Drawing; -using System.Drawing.Imaging; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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) - { - Bitmap file = new Bitmap(filename); - - ITerrainChannel retval = new TerrainChannel(file.Width, file.Height); - - int x, y; - for (x = 0; x < file.Width; x++) - { - for (y = 0; y < file.Height; y++) - { - retval[x, y] = file.GetPixel(x, y).GetBrightness() * 128; - } - } - - return retval; - } - - public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) - { - throw new NotImplementedException(); - } - - /// - /// 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); - } - - #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 Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) - { - Bitmap bmp = new Bitmap(map.Width, map.Height); - - 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 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; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.cs deleted file mode 100644 index c2ac9d0423..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/JPEG.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. - */ - -using System; -using System.Drawing; -using System.Drawing.Imaging; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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 void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Jpeg); - } - - #endregion - - public override string ToString() - { - return "JPEG"; - } - - private 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; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs deleted file mode 100644 index 6ed73401b7..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/LLRAW.cs +++ /dev/null @@ -1,148 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders -{ - public class LLRAW : ITerrainLoader - { - #region ITerrainLoader Members - - public ITerrainChannel LoadFile(string filename) - { - TerrainChannel retval = new TerrainChannel(); - - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - BinaryReader bs = new BinaryReader(s); - int x, y; - for (y = 0; y < retval.Height; y++) - { - for (x = 0; x < retval.Width; x++) - { - retval[x, y] = (double) bs.ReadByte() * ((double) bs.ReadByte() / 127.0); - bs.ReadBytes(11); // Advance the stream to next bytes. - } - } - - bs.Close(); - s.Close(); - - return retval; - } - - public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) - { - throw new NotImplementedException(); - } - - public void SaveFile(string filename, ITerrainChannel map) - { - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); - BinaryWriter binStream = new BinaryWriter(s); - - // Generate a smegging big lookup table to speed the operation up (it needs it) - double[] lookupHeightTable = new double[65536]; - int i, j, x, y; - for (i = 0; i < 256; i++) - { - for (j = 0; j < 256; j++) - { - lookupHeightTable[i + (j * 256)] = ((double) i * ((double) j / 127.0)); - } - } - - // Output the calculated raw - for (y = 0; y < map.Height; y++) - { - for (x = 0; x < map.Width; x++) - { - double t = map[x, y]; - double min = double.MaxValue; - int index = 0; - - for (i = 0; i < 65536; i++) - { - if (Math.Abs(t - lookupHeightTable[i]) < min) - { - min = Math.Abs(t - lookupHeightTable[i]); - index = i; - } - } - - byte red = (byte) (index & 0xFF); - byte green = (byte) ((index >> 8) & 0xFF); - byte blue = 20; - byte alpha1 = 0; // Land Parcels - byte alpha2 = 0; // For Sale Land - byte alpha3 = 0; // Public Edit Object - byte alpha4 = 0; // Public Edit Land - byte alpha5 = 255; // Safe Land - byte alpha6 = 255; // Flying Allowed - byte alpha7 = 255; // Create Landmark - byte alpha8 = 255; // Outside Scripts - 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(); - s.Close(); - } - - - public string FileExtension - { - get { return ".raw"; } - } - - #endregion - - public override string ToString() - { - return "LL/SL RAW"; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/PNG.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/PNG.cs deleted file mode 100644 index 16f1e3c24d..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/PNG.cs +++ /dev/null @@ -1,47 +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 OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders -{ - internal class PNG : GenericSystemDrawing - { - public override void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Png); - } - - public override string ToString() - { - return "PNG"; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs deleted file mode 100644 index edc379b884..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/RAW32.cs +++ /dev/null @@ -1,153 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders -{ - public class RAW32 : ITerrainLoader - { - #region ITerrainLoader Members - - public string FileExtension - { - get { return ".r32"; } - } - - public ITerrainChannel LoadFile(string filename) - { - TerrainChannel retval = new TerrainChannel(); - - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - BinaryReader bs = new BinaryReader(s); - int x, y; - for (y = 0; y < retval.Height; y++) - { - for (x = 0; x < retval.Width; x++) - { - retval[x, y] = bs.ReadSingle(); - } - } - - bs.Close(); - 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 currFileXOffset = 0; - 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 x, y; - // for each Y within our Y offset - for (y = 0; y < sectionHeight; y++) - { - 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 - 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 void SaveFile(string filename, ITerrainChannel map) - { - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Create, FileAccess.Write); - BinaryWriter bs = new BinaryWriter(s); - - int x, y; - for (y = 0; y < map.Height; y++) - { - for (x = 0; x < map.Width; x++) - { - bs.Write((float) map[x, y]); - } - } - - bs.Close(); - s.Close(); - } - - #endregion - - public override string ToString() - { - return "RAW32"; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/TIFF.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/TIFF.cs deleted file mode 100644 index 39c2428f87..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/TIFF.cs +++ /dev/null @@ -1,47 +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 OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders -{ - internal class TIFF : GenericSystemDrawing - { - public override void SaveFile(string filename, ITerrainChannel map) - { - Bitmap colours = CreateGrayscaleBitmapFromMap(map); - - colours.Save(filename, ImageFormat.Tiff); - } - - public override string ToString() - { - return "TIFF"; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.cs deleted file mode 100644 index 2a4a8f84c5..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FileLoaders/Terragen.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.Text; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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) - { - TerrainChannel retval = new TerrainChannel(); - - FileInfo file = new FileInfo(filename); - FileStream s = file.Open(FileMode.Open, FileAccess.Read); - BinaryReader bs = new BinaryReader(s); - - bool eof = false; - if (ASCIIEncoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") - { - // Terragen file - while (eof == false) - { - int w = 256; - int h = 256; - string tmp = ASCIIEncoding.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, y; - for (x = 0; x < w; x++) - { - for (y = 0; y < h; y++) - { - retval[x, y] = (double) baseHeight + (double) bs.ReadInt16() * (double) heightScale / 65536.0; - } - } - break; - default: - bs.ReadInt32(); - break; - } - } - } - - bs.Close(); - s.Close(); - - return retval; - } - - public void SaveFile(string filename, ITerrainChannel map) - { - char[] header = "TERRAGENTERRAIN".ToCharArray(); - 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"; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/FlattenArea.cs b/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/FlattenArea.cs deleted file mode 100644 index 1e0b1519a5..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/FlattenArea.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 OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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; - double avg; - - 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; - } - } - } - - 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/Terrain/FloodBrushes/LowerArea.cs b/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/LowerArea.cs deleted file mode 100644 index 410d0cf06d..0000000000 --- a/OpenSim/Region/Environment/Modules/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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/NoiseArea.cs deleted file mode 100644 index 2ea1b90329..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/NoiseArea.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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FloodBrushes -{ - public class NoiseArea : ITerrainFloodEffect - { - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - int x, y; - for (x = 0; x < map.Width; x++) - { - 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/Terrain/FloodBrushes/RaiseArea.cs b/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/RaiseArea.cs deleted file mode 100644 index 4ea06c8280..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/RaiseArea.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.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FloodBrushes -{ - public class RaiseArea : ITerrainFloodEffect - { - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - int x, y; - for (x = 0; x < map.Width; x++) - { - 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/Terrain/FloodBrushes/RevertArea.cs b/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/RevertArea.cs deleted file mode 100644 index 198b309c0f..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/RevertArea.cs +++ /dev/null @@ -1,60 +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.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.FloodBrushes -{ - public class RevertArea : ITerrainFloodEffect - { - private readonly ITerrainChannel m_revertmap; - - public RevertArea(ITerrainChannel revertmap) - { - m_revertmap = revertmap; - } - - #region ITerrainFloodEffect Members - - public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) - { - int x, y; - 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 - strength)) + (m_revertmap[x, y] * strength); - } - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/Environment/Modules/Terrain/FloodBrushes/SmoothArea.cs deleted file mode 100644 index 49d88835ee..0000000000 --- a/OpenSim/Region/Environment/Modules/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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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; - - 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/Terrain/ITerrainEffect.cs b/OpenSim/Region/Environment/Modules/Terrain/ITerrainEffect.cs deleted file mode 100644 index 96e92f2217..0000000000 --- a/OpenSim/Region/Environment/Modules/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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain -{ - public interface ITerrainEffect - { - void RunEffect(ITerrainChannel map); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/ITerrainFloodEffect.cs b/OpenSim/Region/Environment/Modules/Terrain/ITerrainFloodEffect.cs deleted file mode 100644 index 7d33bf840c..0000000000 --- a/OpenSim/Region/Environment/Modules/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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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/Terrain/ITerrainLoader.cs b/OpenSim/Region/Environment/Modules/Terrain/ITerrainLoader.cs deleted file mode 100644 index c718a3230a..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/ITerrainLoader.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 OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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); - void SaveFile(string filename, ITerrainChannel map); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/ITerrainModule.cs b/OpenSim/Region/Environment/Modules/Terrain/ITerrainModule.cs deleted file mode 100644 index d1ea2a47c9..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/ITerrainModule.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace OpenSim.Region.Environment.Modules.Terrain -{ - public interface ITerrainModule - { - void LoadFromFile(string filename); - void SaveToFile(string filename); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/ITerrainPaintableEffect.cs b/OpenSim/Region/Environment/Modules/Terrain/ITerrainPaintableEffect.cs deleted file mode 100644 index 07fcb721f4..0000000000 --- a/OpenSim/Region/Environment/Modules/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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain -{ - public interface ITerrainPaintableEffect - { - void PaintEffect(ITerrainChannel map, double x, double y, double strength, double duration); - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/MapImageModule.cs b/OpenSim/Region/Environment/Modules/Terrain/MapImageModule.cs deleted file mode 100644 index 763735f016..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/MapImageModule.cs +++ /dev/null @@ -1,168 +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 Nini.Config; -using OpenJPEGNet; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.Terrain -{ - internal class MapImageModule : IMapImageGenerator, IRegionModule - { - private Scene m_scene; - - #region IMapImageGenerator Members - - public byte[] WriteJpeg2000Image(string gradientmap) - { - byte[] imageData = null; - - Bitmap bmp = TerrainToBitmap(gradientmap); - - try - { - imageData = OpenJPEG.EncodeFromImage(bmp, 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_scene.RegisterModuleInterface(this); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "MapImageModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - private void ShadeBuildings(ref 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, y, w, h; - x = (int) (primitive.AbsolutePosition.X - (primitive.Scale.X / 2)); - y = (int) (primitive.AbsolutePosition.Y - (primitive.Scale.Y / 2)); - w = (int) primitive.Scale.X; - 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 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(ref bmp); - return bmp; - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs deleted file mode 100644 index cfb1f60746..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/ErodeSphere.cs +++ /dev/null @@ -1,312 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - /// - /// Hydraulic Erosion Brush - /// - public class ErodeSphere : ITerrainPaintableEffect - { - private double rainHeight = 0.2; - private int rounds = 10; - private NeighbourSystem type = NeighbourSystem.Moore; // Parameter - private double waterSaturation = 0.30; // Can carry 1% of water in height - - #region Supporting Functions - - private int[] Neighbours(NeighbourSystem type, int index) - { - int[] coord = new int[2]; - - index++; - - switch (type) - { - 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, double rx, double ry, 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++) - { - 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]; - - int NEIGHBOUR_ME = 4; - - int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; - - 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) - { - 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 (sediment[x, y] > 0) - map[x, y] += sediment[x, y]; - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/FlattenSphere.cs deleted file mode 100644 index d907ed2b1c..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/FlattenSphere.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 OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - public class FlattenSphere : ITerrainPaintableEffect - { -// TODO: unused -// private 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; - -// 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; -// } - - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, double rx, double ry, 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; - - double sum = 0.0; - double step2 = 0.0; - double avg = 0.0; - - // compute delta map - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - double z = SphericalFactor(x, y, rx, ry, strength); - - if (z > 0) // add in non-zero amount - { - sum += map[x, y] * z; - step2 += z; - } - } - } - - avg = sum / step2; - - // blend in map - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - double z = 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)) + (avg * z); - } - } - } - } - - #endregion - - private double SphericalFactor(double x, double y, double rx, double ry, double size) - { - double z = size * size - ((x - rx) * (x - rx) + (y - ry) * (y - ry)); - return z; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/LowerSphere.cs deleted file mode 100644 index ead1a49797..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/LowerSphere.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.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - public class LowerSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - for (x = 0; x < map.Width; x++) - { - // Skip everything unlikely to be affected - if (Math.Abs(x - rx) > strength * 1.1) - continue; - - for (y = 0; y < map.Height; y++) - { - // Skip everything unlikely to be affected - if (Math.Abs(y - ry) > strength * 1.1) - 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) - map[x, y] -= z * duration; - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/NoiseSphere.cs deleted file mode 100644 index e3babbf85a..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/NoiseSphere.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 System; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - public class NoiseSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - for (x = 0; x < map.Width; x++) - { - // Skip everything unlikely to be affected - if (Math.Abs(x - rx) > strength * 1.1) - continue; - - for (y = 0; y < map.Height; y++) - { - // Skip everything unlikely to be affected - if (Math.Abs(y - ry) > strength * 1.1) - 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((double) x / (double) Constants.RegionSize, (double) y / (double) Constants.RegionSize, 8, 1.0); - - if (z > 0.0) - map[x, y] += noise * z * duration; - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/OlsenSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/OlsenSphere.cs deleted file mode 100644 index 153fc15a84..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/OlsenSphere.cs +++ /dev/null @@ -1,225 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.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 double nConst = 1024.0; - private NeighbourSystem type = NeighbourSystem.Moore; // Parameter - - #region Supporting Functions - - private int[] Neighbours(NeighbourSystem type, int index) - { - int[] coord = new int[2]; - - index++; - - switch (type) - { - 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 double SphericalFactor(double x, double y, double rx, double ry, double size) - { - double z = size * size - ((x - rx) * (x - rx) + (y - ry) * (y - ry)); - return z; - } - - private enum NeighbourSystem - { - Moore, - VonNeumann - } ; - - #endregion - - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - - for (x = 0; x < map.Width; x++) - { - for (y = 0; y < map.Height; y++) - { - double z = SphericalFactor(x, y, rx, ry, strength); - - if (z > 0) // add in non-zero amount - { - int NEIGHBOUR_ME = 4; - int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; - - double max = Double.MinValue; - int loc = 0; - double cellmax = 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; - - cellmax = map[x, y] - map[coords[0], coords[1]]; - if (cellmax > max) - { - max = cellmax; - loc = j; - } - } - } - - double T = nConst / ((map.Width + map.Height) / 2); - // 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 - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RaiseSphere.cs deleted file mode 100644 index 8d61a7e023..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RaiseSphere.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.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - public class RaiseSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - for (x = 0; x < map.Width; x++) - { - // Skip everything unlikely to be affected - if (Math.Abs(x - rx) > strength * 1.1) - continue; - - for (y = 0; y < map.Height; y++) - { - // Skip everything unlikely to be affected - if (Math.Abs(y - ry) > strength * 1.1) - 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) - map[x, y] += z * duration; - } - } - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RevertSphere.cs deleted file mode 100644 index ee0edb5759..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/RevertSphere.cs +++ /dev/null @@ -1,82 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - public class RevertSphere : ITerrainPaintableEffect - { - private ITerrainChannel m_revertmap; - - public RevertSphere(ITerrainChannel revertmap) - { - m_revertmap = revertmap; - } - - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - if (duration > 1.0) - duration = 1.0; - if (duration < 0) - return; - - int x, y; - for (x = 0; x < map.Width; x++) - { - // Skip everything unlikely to be affected - if (Math.Abs(x - rx) > strength * 1.1) - continue; - - for (y = 0; y < map.Height; y++) - { - // Skip everything unlikely to be affected - if (Math.Abs(y - ry) > strength * 1.1) - 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 - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/SmoothSphere.cs deleted file mode 100644 index 86a01cc959..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/SmoothSphere.cs +++ /dev/null @@ -1,93 +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.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - public class SmoothSphere : ITerrainPaintableEffect - { - #region ITerrainPaintableEffect Members - - public void PaintEffect(ITerrainChannel map, double rx, double ry, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - double[,] tweak = new double[map.Width,map.Height]; - - double n, l; - double area = strength; - double step = strength / 4.0; - - // 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; - - for (n = 0.0 - area; n < area; n += step) - { - 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++) - { - 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 - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/WeatherSphere.cs b/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/WeatherSphere.cs deleted file mode 100644 index f46ba8f04d..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/PaintBrushes/WeatherSphere.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 OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain.PaintBrushes -{ - /// - /// Thermal Weathering Paint Brush - /// - public class WeatherSphere : ITerrainPaintableEffect - { - private double talus = 0.2; // Number of meters max difference before stop eroding. Tweakage required. - private NeighbourSystem type = NeighbourSystem.Moore; // Parameter - - #region Supporting Functions - - private int[] Neighbours(NeighbourSystem type, int index) - { - int[] coord = new int[2]; - - index++; - - switch (type) - { - 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, double rx, double ry, double strength, double duration) - { - strength = TerrainUtil.MetersToSphericalStrength(strength); - - int x, y; - - 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 - { - int NEIGHBOUR_ME = 4; - - int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; - - 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 - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/TerrainChannel.cs b/OpenSim/Region/Environment/Modules/Terrain/TerrainChannel.cs deleted file mode 100644 index 1344715c9e..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/TerrainChannel.cs +++ /dev/null @@ -1,157 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain -{ - /// - /// A new version of the old Channel class, simplified - /// - public class TerrainChannel : ITerrainChannel - { - private readonly bool[,] taint; - private double[,] map; - - public TerrainChannel() - { - map = new double[Constants.RegionSize,Constants.RegionSize]; - taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16]; - - int x; - for (x = 0; x < Constants.RegionSize; x++) - { - int y; - for (y = 0; y < Constants.RegionSize; 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; - } - } - } - } - - public TerrainChannel(double[,] import) - { - map = import; - taint = new bool[import.GetLength(0),import.GetLength(1)]; - } - - public TerrainChannel(bool createMap) - { - if (createMap) - { - map = new double[Constants.RegionSize,Constants.RegionSize]; - taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16]; - } - } - - public TerrainChannel(int w, int h) - { - map = new double[w,h]; - taint = new bool[w / 16,h / 16]; - } - - #region ITerrainChannel Members - - public int Width - { - get { return map.GetLength(0); } - } - - public int Height - { - get { return map.GetLength(1); } - } - - public ITerrainChannel MakeCopy() - { - TerrainChannel copy = new TerrainChannel(false); - copy.map = (double[,]) map.Clone(); - - return copy; - } - - public float[] GetFloatsSerialised() - { - float[] heights = new float[Width * Height]; - int i; - - for (i = 0; i < Width * Height; i++) - { - heights[i] = (float) map[i % Width, i / Width]; - } - - return heights; - } - - public double[,] GetDoubles() - { - return map; - } - - public double this[int x, int y] - { - get { return map[x, y]; } - set - { - if (map[x, y] != value) - { - taint[x / 16, y / 16] = true; - map[x, y] = value; - } - } - } - - public bool Tainted(int x, int y) - { - if (taint[x / 16, y / 16]) - { - taint[x / 16, y / 16] = false; - return true; - } - else - { - return false; - } - } - - #endregion - - public TerrainChannel Copy() - { - TerrainChannel copy = new TerrainChannel(false); - copy.map = (double[,]) map.Clone(); - - return copy; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/TerrainException.cs b/OpenSim/Region/Environment/Modules/Terrain/TerrainException.cs deleted file mode 100644 index d357063ab0..0000000000 --- a/OpenSim/Region/Environment/Modules/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.Terrain -{ - public class TerrainException : Exception - { - public TerrainException() : base() - { - } - - 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/Terrain/TerrainModule.cs b/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs deleted file mode 100644 index 67acef7e83..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs +++ /dev/null @@ -1,734 +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 libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Modules.ModuleFramework; -using OpenSim.Region.Environment.Modules.Terrain.FileLoaders; -using OpenSim.Region.Environment.Modules.Terrain.FloodBrushes; -using OpenSim.Region.Environment.Modules.Terrain.PaintBrushes; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.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 = false; - - #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); - 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)); - } - } - CheckForTerrainUpdates(); - m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); - return; - } - } - m_log.Error("[TERRAIN]: Unable to load heightmap, no file loader availible 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: {0}: 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; - - if (pluginType.GetInterface("ITerrainEffect", false) != null) - { - ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); - if (!m_plugineffects.ContainsKey(pluginType.Name)) - { - m_plugineffects.Add(pluginType.Name, terEffect); - m_log.Info("E ... " + pluginType.Name); - } else - { - m_log.Warn("E ... " + pluginType.Name + " (Already added)"); - } - } - 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 ... " + pluginType.Name); - } - } - catch (AmbiguousMatchException) - { - } - } - } - catch (BadImageFormatException) - { - } - } - } - - #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(); - m_scene.CreateTerrainTexture(true); - } - } - - /// - /// Processes commandline input. Do not call directly. - /// - /// Commandline arguments - private void EventManager_OnPluginConsole(string[] args) - { - if (args[0] == "terrain") - { - 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; - } - - /// - /// Checks to see if the terrain has been modified since last check - /// - private void CheckForTerrainUpdates() - { - 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)) - { - SendToClients(serialised, x, y); - shouldTaint = true; - } - } - } - if (shouldTaint) - { - m_tainted = true; - } - } - - /// - /// 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(float height, float seconds, byte size, byte action, float north, float west, - float south, float east, IClientAPI remoteClient) - { - // Not a good permissions check, if in area mode, need to check the entire area. - if (m_scene.PermissionsMngr.CanTerraform(remoteClient.AgentId, new LLVector3(north, west, 0))) - { - if (north == south && east == west) - { - if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) - { - m_painteffects[(StandardTerrainEffects) action].PaintEffect( - m_channel, west, south, size, seconds); - - CheckForTerrainUpdates(); - } - else - { - m_log.Debug("Unknown terrain brush type " + action); - } - } - else - { - if (m_floodeffects.ContainsKey((StandardTerrainEffects) action)) - { - bool[,] fillArea = new bool[m_channel.Width,m_channel.Height]; - fillArea.Initialize(); - - int x; - for (x = 0; x < m_channel.Width; x++) - { - int y; - for (y = 0; y < m_channel.Height; y++) - { - if (x < east && x > west) - { - if (y < north && y > south) - { - fillArea[x, y] = true; - } - } - } - } - - m_floodeffects[(StandardTerrainEffects) action].FloodEffect( - m_channel, fillArea, size); - - CheckForTerrainUpdates(); - } - else - { - m_log.Debug("Unknown terrain flood type " + action); - } - } - } - } - - #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 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 avg; - 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]; - } - } - - 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", 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", 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", 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", 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", 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", 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", InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified."); - multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); - - Command bakeRegionCommand = - new Command("bake", InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); - Command revertRegionCommand = - new Command("revert", InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); - - // Debug - Command showDebugStatsCommand = - new Command("stats", InterfaceShowDebugStats, - "Shows some information about the regions heightmap for debugging purposes."); - - Command experimentalBrushesCommand = - new Command("newbrushes", 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", 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); - - // Add this to our scene so scripts can call these functions - m_scene.RegisterModuleCommander("Terrain", m_commander); - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Terrain/TerrainUtil.cs b/OpenSim/Region/Environment/Modules/Terrain/TerrainUtil.cs deleted file mode 100644 index d4d09227b5..0000000000 --- a/OpenSim/Region/Environment/Modules/Terrain/TerrainUtil.cs +++ /dev/null @@ -1,133 +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.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Terrain -{ - public static class TerrainUtil - { - public static double MetersToSphericalStrength(double size) - { - return Math.Pow(2, size); - } - - public static double SphericalFactor(double x, double y, double rx, double ry, double size) - { - return size * size - ((x - rx) * (x - rx) + (y - ry) * (y - ry)); - } - - public 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; - - 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; - } - - private static double Noise(double x, double y) - { - int n = (int) x + (int) (y * 749); - n = (n << 13) ^ n; - return (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); - } - - private static double SmoothedNoise1(double x, double y) - { - double corners = (Noise(x - 1, y - 1) + Noise(x + 1, y - 1) + Noise(x - 1, y + 1) + Noise(x + 1, y + 1)) / 16; - double sides = (Noise(x - 1, y) + Noise(x + 1, y) + Noise(x, y - 1) + Noise(x, y + 1)) / 8; - double center = Noise(x, y) / 4; - return corners + sides + center; - } - - private static double Interpolate(double x, double y, double z) - { - return (x * (1.0 - z)) + (y * z); - } - - private static double InterpolatedNoise(double x, double y) - { - int integer_X = (int) (x); - double fractional_X = x - integer_X; - - int integer_Y = (int) y; - double fractional_Y = y - integer_Y; - - double v1 = SmoothedNoise1(integer_X, integer_Y); - double v2 = SmoothedNoise1(integer_X + 1, integer_Y); - double v3 = SmoothedNoise1(integer_X, integer_Y + 1); - double v4 = SmoothedNoise1(integer_X + 1, integer_Y + 1); - - double i1 = Interpolate(v1, v2, fractional_X); - double i2 = Interpolate(v3, v4, fractional_X); - - return Interpolate(i1, i2, fractional_Y); - } - - public static double PerlinNoise2D(double x, double y, int octaves, double persistence) - { - double frequency = 0.0; - double amplitude = 0.0; - double total = 0.0; - - for (int i = 0; i < octaves; i++) - { - frequency = Math.Pow(2, i); - amplitude = Math.Pow(persistence, i); - - total += InterpolatedNoise(x * frequency, y * frequency) * amplitude; - } - return total; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/TreePopulatorModule.cs b/OpenSim/Region/Environment/Modules/TreePopulatorModule.cs deleted file mode 100644 index 2051a0ffd6..0000000000 --- a/OpenSim/Region/Environment/Modules/TreePopulatorModule.cs +++ /dev/null @@ -1,248 +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 Axiom.Math; -using libsecondlife; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules -{ - /// - /// Version 2.0 - Very hacky compared to the original. Will fix original and release as 0.3 later. - /// - public class TreePopulatorModule : IRegionModule - { - private Scene m_scene; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private List m_trees; - - public double m_tree_density = 50.0; // Aim for this many per region - public double m_tree_updates = 1000.0; // MS between updates - - public void Initialise(Scene scene, IConfigSource config) - { - try - { - m_tree_density = config.Configs["Trees"].GetDouble("tree_density", m_tree_density); - } - catch (Exception) - { } - - m_trees = new List(); - m_scene = scene; - - m_scene.EventManager.OnPluginConsole += new EventManager.OnPluginConsoleDelegate(EventManager_OnPluginConsole); - - Timer CalculateTrees = new Timer(m_tree_updates); - CalculateTrees.Elapsed += new ElapsedEventHandler(CalculateTrees_Elapsed); - CalculateTrees.Start(); - m_log.Debug("[TREES]: Initialised tree module"); - } - - void EventManager_OnPluginConsole(string[] args) - { - if (args[0] == "tree") - { - m_log.Debug("[TREES]: New tree planting"); - CreateTree(new LLVector3(128.0f, 128.0f, 0.0f)); - } - } - - void growTrees() - { - foreach (LLUUID 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 LLVector3(0.1f, 0.1f, 0.1f); - s_tree.SendFullUpdateToAllClients(); - //s_tree.ScheduleTerseUpdate(); - } - else - { - m_trees.Remove(tree); - } - } - } - - void seedTrees() - { - foreach (LLUUID 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); - } - } - } - - void killTrees() - { - foreach (LLUUID 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 (LLUUID 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.RemoveEntity(selectedTree.ParentGroup); - m_trees.Remove(selectedTree.ParentGroup.UUID); - - m_scene.ForEachClient(delegate(IClientAPI controller) - { - controller.SendKillObject(m_scene.RegionInfo.RegionHandle, - selectedTree.LocalId); - }); - - break; - } - else - { - 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) - { - LLVector3 position = new LLVector3(); - - 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; - - CreateTree(position); - } - - private void CreateTree(LLVector3 position) - { - position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y]; - - SceneObjectGroup tree = - m_scene.AddTree(new LLVector3(0.1f, 0.1f, 0.1f), - LLQuaternion.Identity, - position, - Tree.Cypress1, - false); - - m_trees.Add(tree.UUID); - tree.SendGroupFullUpdate(); - } - - void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e) - { - growTrees(); - seedTrees(); - killTrees(); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "TreePopulatorModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - } -}