* 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.
0.6.0-stable
Adam Frisby 2008-04-30 21:16:36 +00:00
parent 19723767a9
commit f5c312bc3c
78 changed files with 8880 additions and 16880 deletions

View File

@ -1,333 +1,333 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using libsecondlife; using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Agent.AssetDownload
{ {
public class AssetDownloadModule : IRegionModule public class AssetDownloadModule : IRegionModule
{ {
private Scene m_scene; private Scene m_scene;
private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>(); private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
/// ///
/// Assets requests (for each user) which are waiting for asset server data. This includes texture requests /// Assets requests (for each user) which are waiting for asset server data. This includes texture requests
/// </summary> /// </summary>
private Dictionary<LLUUID, Dictionary<LLUUID,AssetRequest>> RequestedAssets; private Dictionary<LLUUID, Dictionary<LLUUID,AssetRequest>> RequestedAssets;
/// <summary> /// <summary>
/// Asset requests with data which are ready to be sent back to requesters. This includes textures. /// Asset requests with data which are ready to be sent back to requesters. This includes textures.
/// </summary> /// </summary>
private List<AssetRequest> AssetRequests; private List<AssetRequest> AssetRequests;
public AssetDownloadModule() public AssetDownloadModule()
{ {
RequestedAssets = new Dictionary<LLUUID, Dictionary<LLUUID, AssetRequest>>(); RequestedAssets = new Dictionary<LLUUID, Dictionary<LLUUID, AssetRequest>>();
AssetRequests = new List<AssetRequest>(); AssetRequests = new List<AssetRequest>();
} }
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{ {
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
// scene.EventManager.OnNewClient += NewClient; // scene.EventManager.OnNewClient += NewClient;
} }
if (m_scene == null) if (m_scene == null)
{ {
m_scene = scene; m_scene = scene;
// m_thread = new Thread(new ThreadStart(RunAssetQueue)); // m_thread = new Thread(new ThreadStart(RunAssetQueue));
// m_thread.Name = "AssetDownloadQueueThread"; // m_thread.Name = "AssetDownloadQueueThread";
// m_thread.IsBackground = true; // m_thread.IsBackground = true;
// m_thread.Start(); // m_thread.Start();
// OpenSim.Framework.ThreadTracker.Add(m_thread); // OpenSim.Framework.ThreadTracker.Add(m_thread);
} }
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "AssetDownloadModule"; } get { return "AssetDownloadModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return true; } get { return true; }
} }
public void NewClient(IClientAPI client) public void NewClient(IClientAPI client)
{ {
// client.OnRequestAsset += AddAssetRequest; // client.OnRequestAsset += AddAssetRequest;
} }
/// <summary> /// <summary>
/// Make an asset request the result of which will be packeted up and sent directly back to the client. /// Make an asset request the result of which will be packeted up and sent directly back to the client.
/// </summary> /// </summary>
/// <param name="userInfo"></param> /// <param name="userInfo"></param>
/// <param name="transferRequest"></param> /// <param name="transferRequest"></param>
public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest)
{ {
LLUUID requestID = null; LLUUID requestID = null;
byte source = 2; byte source = 2;
if (transferRequest.TransferInfo.SourceType == 2) if (transferRequest.TransferInfo.SourceType == 2)
{ {
//direct asset request //direct asset request
requestID = new LLUUID(transferRequest.TransferInfo.Params, 0); requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
} }
else if (transferRequest.TransferInfo.SourceType == 3) else if (transferRequest.TransferInfo.SourceType == 3)
{ {
//inventory asset request //inventory asset request
requestID = new LLUUID(transferRequest.TransferInfo.Params, 80); requestID = new LLUUID(transferRequest.TransferInfo.Params, 80);
source = 3; source = 3;
//Console.WriteLine("asset request " + requestID); //Console.WriteLine("asset request " + requestID);
} }
//not found asset //not found asset
// so request from asset server // so request from asset server
Dictionary<LLUUID, AssetRequest> userRequests = null; Dictionary<LLUUID, AssetRequest> userRequests = null;
if (RequestedAssets.TryGetValue(userInfo.AgentId, out userRequests)) if (RequestedAssets.TryGetValue(userInfo.AgentId, out userRequests))
{ {
if (!userRequests.ContainsKey(requestID)) if (!userRequests.ContainsKey(requestID))
{ {
AssetRequest request = new AssetRequest(); AssetRequest request = new AssetRequest();
request.RequestUser = userInfo; request.RequestUser = userInfo;
request.RequestAssetID = requestID; request.RequestAssetID = requestID;
request.TransferRequestID = transferRequest.TransferInfo.TransferID; request.TransferRequestID = transferRequest.TransferInfo.TransferID;
request.AssetRequestSource = source; request.AssetRequestSource = source;
request.Params = transferRequest.TransferInfo.Params; request.Params = transferRequest.TransferInfo.Params;
userRequests[requestID] = request; userRequests[requestID] = request;
m_scene.AssetCache.GetAsset(requestID, AssetCallback, false); m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
} }
} }
else else
{ {
userRequests = new Dictionary<LLUUID, AssetRequest>(); userRequests = new Dictionary<LLUUID, AssetRequest>();
AssetRequest request = new AssetRequest(); AssetRequest request = new AssetRequest();
request.RequestUser = userInfo; request.RequestUser = userInfo;
request.RequestAssetID = requestID; request.RequestAssetID = requestID;
request.TransferRequestID = transferRequest.TransferInfo.TransferID; request.TransferRequestID = transferRequest.TransferInfo.TransferID;
request.AssetRequestSource = source; request.AssetRequestSource = source;
request.Params = transferRequest.TransferInfo.Params; request.Params = transferRequest.TransferInfo.Params;
userRequests.Add(requestID, request); userRequests.Add(requestID, request);
RequestedAssets[userInfo.AgentId] = userRequests; RequestedAssets[userInfo.AgentId] = userRequests;
m_scene.AssetCache.GetAsset(requestID, AssetCallback, false); m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
} }
} }
public void AssetCallback(LLUUID assetID, AssetBase asset) public void AssetCallback(LLUUID assetID, AssetBase asset)
{ {
if (asset != null) if (asset != null)
{ {
foreach (Dictionary<LLUUID, AssetRequest> userRequests in RequestedAssets.Values) foreach (Dictionary<LLUUID, AssetRequest> userRequests in RequestedAssets.Values)
{ {
if (userRequests.ContainsKey(assetID)) if (userRequests.ContainsKey(assetID))
{ {
AssetRequest req = userRequests[assetID]; AssetRequest req = userRequests[assetID];
if (req != null) if (req != null)
{ {
req.AssetInf = asset; req.AssetInf = asset;
req.NumPackets = CalculateNumPackets(asset.Data); req.NumPackets = CalculateNumPackets(asset.Data);
userRequests.Remove(assetID); userRequests.Remove(assetID);
AssetRequests.Add(req); AssetRequests.Add(req);
} }
} }
} }
} }
} }
// TODO: unused // TODO: unused
// private void RunAssetQueue() // private void RunAssetQueue()
// { // {
// while (true) // while (true)
// { // {
// try // try
// { // {
// ProcessAssetQueue(); // ProcessAssetQueue();
// Thread.Sleep(500); // Thread.Sleep(500);
// } // }
// catch (Exception) // catch (Exception)
// { // {
// // m_log.Error("[ASSET CACHE]: " + e.ToString()); // // m_log.Error("[ASSET CACHE]: " + e.ToString());
// } // }
// } // }
// } // }
// TODO: unused // TODO: unused
// /// <summary> // /// <summary>
// /// Process the asset queue which sends packets directly back to the client. // /// Process the asset queue which sends packets directly back to the client.
// /// </summary> // /// </summary>
// private void ProcessAssetQueue() // private void ProcessAssetQueue()
// { // {
// //should move the asset downloading to a module, like has been done with texture downloading // //should move the asset downloading to a module, like has been done with texture downloading
// if (AssetRequests.Count == 0) // if (AssetRequests.Count == 0)
// { // {
// //no requests waiting // //no requests waiting
// return; // return;
// } // }
// // if less than 5, do all of them // // if less than 5, do all of them
// int num = Math.Min(5, AssetRequests.Count); // int num = Math.Min(5, AssetRequests.Count);
// AssetRequest req; // AssetRequest req;
// for (int i = 0; i < num; i++) // for (int i = 0; i < num; i++)
// { // {
// req = (AssetRequest)AssetRequests[i]; // req = (AssetRequest)AssetRequests[i];
// //Console.WriteLine("sending asset " + req.RequestAssetID); // //Console.WriteLine("sending asset " + req.RequestAssetID);
// TransferInfoPacket Transfer = new TransferInfoPacket(); // TransferInfoPacket Transfer = new TransferInfoPacket();
// Transfer.TransferInfo.ChannelType = 2; // Transfer.TransferInfo.ChannelType = 2;
// Transfer.TransferInfo.Status = 0; // Transfer.TransferInfo.Status = 0;
// Transfer.TransferInfo.TargetType = 0; // Transfer.TransferInfo.TargetType = 0;
// if (req.AssetRequestSource == 2) // if (req.AssetRequestSource == 2)
// { // {
// Transfer.TransferInfo.Params = new byte[20]; // Transfer.TransferInfo.Params = new byte[20];
// Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); // Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
// int assType = (int)req.AssetInf.Type; // int assType = (int)req.AssetInf.Type;
// Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); // Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
// } // }
// else if (req.AssetRequestSource == 3) // else if (req.AssetRequestSource == 3)
// { // {
// Transfer.TransferInfo.Params = req.Params; // Transfer.TransferInfo.Params = req.Params;
// // Transfer.TransferInfo.Params = new byte[100]; // // Transfer.TransferInfo.Params = new byte[100];
// //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); // //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
// //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); // //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
// } // }
// Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length; // Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length;
// Transfer.TransferInfo.TransferID = req.TransferRequestID; // Transfer.TransferInfo.TransferID = req.TransferRequestID;
// req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset); // req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset);
// if (req.NumPackets == 1) // if (req.NumPackets == 1)
// { // {
// TransferPacketPacket TransferPacket = new TransferPacketPacket(); // TransferPacketPacket TransferPacket = new TransferPacketPacket();
// TransferPacket.TransferData.Packet = 0; // TransferPacket.TransferData.Packet = 0;
// TransferPacket.TransferData.ChannelType = 2; // TransferPacket.TransferData.ChannelType = 2;
// TransferPacket.TransferData.TransferID = req.TransferRequestID; // TransferPacket.TransferData.TransferID = req.TransferRequestID;
// TransferPacket.TransferData.Data = req.AssetInf.Data; // TransferPacket.TransferData.Data = req.AssetInf.Data;
// TransferPacket.TransferData.Status = 1; // TransferPacket.TransferData.Status = 1;
// req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); // req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
// } // }
// else // else
// { // {
// int processedLength = 0; // int processedLength = 0;
// // libsecondlife hardcodes 1500 as the maximum data chunk size // // libsecondlife hardcodes 1500 as the maximum data chunk size
// int maxChunkSize = 1250; // int maxChunkSize = 1250;
// int packetNumber = 0; // int packetNumber = 0;
// while (processedLength < req.AssetInf.Data.Length) // while (processedLength < req.AssetInf.Data.Length)
// { // {
// TransferPacketPacket TransferPacket = new TransferPacketPacket(); // TransferPacketPacket TransferPacket = new TransferPacketPacket();
// TransferPacket.TransferData.Packet = packetNumber; // TransferPacket.TransferData.Packet = packetNumber;
// TransferPacket.TransferData.ChannelType = 2; // TransferPacket.TransferData.ChannelType = 2;
// TransferPacket.TransferData.TransferID = req.TransferRequestID; // TransferPacket.TransferData.TransferID = req.TransferRequestID;
// int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); // int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
// byte[] chunk = new byte[chunkSize]; // byte[] chunk = new byte[chunkSize];
// Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); // Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
// TransferPacket.TransferData.Data = chunk; // TransferPacket.TransferData.Data = chunk;
// // 0 indicates more packets to come, 1 indicates last packet // // 0 indicates more packets to come, 1 indicates last packet
// if (req.AssetInf.Data.Length - processedLength > maxChunkSize) // if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
// { // {
// TransferPacket.TransferData.Status = 0; // TransferPacket.TransferData.Status = 0;
// } // }
// else // else
// { // {
// TransferPacket.TransferData.Status = 1; // TransferPacket.TransferData.Status = 1;
// } // }
// req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); // req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
// processedLength += chunkSize; // processedLength += chunkSize;
// packetNumber++; // packetNumber++;
// } // }
// } // }
// } // }
// //remove requests that have been completed // //remove requests that have been completed
// for (int i = 0; i < num; i++) // for (int i = 0; i < num; i++)
// { // {
// AssetRequests.RemoveAt(0); // AssetRequests.RemoveAt(0);
// } // }
// } // }
/// <summary> /// <summary>
/// Calculate the number of packets required to send the asset to the client. /// Calculate the number of packets required to send the asset to the client.
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
/// <returns></returns> /// <returns></returns>
private int CalculateNumPackets(byte[] data) private int CalculateNumPackets(byte[] data)
{ {
const uint m_maxPacketSize = 600; const uint m_maxPacketSize = 600;
int numPackets = 1; int numPackets = 1;
if (data.LongLength > m_maxPacketSize) if (data.LongLength > m_maxPacketSize)
{ {
// over max number of bytes so split up file // over max number of bytes so split up file
long restData = data.LongLength - m_maxPacketSize; long restData = data.LongLength - m_maxPacketSize;
int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize); int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize);
numPackets += restPackets; numPackets += restPackets;
} }
return numPackets; return numPackets;
} }
public class AssetRequest public class AssetRequest
{ {
public IClientAPI RequestUser; public IClientAPI RequestUser;
public LLUUID RequestAssetID; public LLUUID RequestAssetID;
public AssetBase AssetInf; public AssetBase AssetInf;
public AssetBase ImageInfo; public AssetBase ImageInfo;
public LLUUID TransferRequestID; public LLUUID TransferRequestID;
public long DataPointer = 0; public long DataPointer = 0;
public int NumPackets = 0; public int NumPackets = 0;
public int PacketCounter = 0; public int PacketCounter = 0;
public bool IsTextureRequest; public bool IsTextureRequest;
public byte AssetRequestSource = 2; public byte AssetRequestSource = 2;
public byte[] Params = null; public byte[] Params = null;
//public bool AssetInCache; //public bool AssetInCache;
//public int TimeRequested; //public int TimeRequested;
public int DiscardLevel = -1; public int DiscardLevel = -1;
public AssetRequest() public AssetRequest()
{ {
} }
} }
} }
} }

View File

@ -1,408 +1,407 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using libsecondlife; using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Communications.Cache;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction
{ {
/// <summary>
/// <summary> /// Manage asset transactions for a single agent.
/// Manage asset transactions for a single agent. /// </summary>
/// </summary> public class AgentAssetTransactions
public class AgentAssetTransactions {
{ //private static readonly log4net.ILog m_log
//private static readonly log4net.ILog m_log // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// Fields
// Fields public LLUUID UserID;
public LLUUID UserID; public Dictionary<LLUUID, AssetXferUploader> XferUploaders = new Dictionary<LLUUID, AssetXferUploader>();
public Dictionary<LLUUID, AssetXferUploader> XferUploaders = new Dictionary<LLUUID, AssetXferUploader>(); public AgentAssetTransactionsManager Manager;
public AgentAssetTransactionsManager Manager; private bool m_dumpAssetsToFile;
private bool m_dumpAssetsToFile;
// Methods
// Methods public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile)
public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile) {
{ UserID = agentID;
UserID = agentID; Manager = manager;
Manager = manager; m_dumpAssetsToFile = dumpAssetsToFile;
m_dumpAssetsToFile = dumpAssetsToFile; }
}
public AssetXferUploader RequestXferUploader(LLUUID transactionID)
public AssetXferUploader RequestXferUploader(LLUUID transactionID) {
{ if (!XferUploaders.ContainsKey(transactionID))
if (!XferUploaders.ContainsKey(transactionID)) {
{ AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile);
AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile);
lock (XferUploaders)
lock (XferUploaders) {
{ XferUploaders.Add(transactionID, uploader);
XferUploaders.Add(transactionID, uploader); }
}
return uploader;
return uploader; }
} return null;
return null; }
}
public void HandleXfer(ulong xferID, uint packetID, byte[] data)
public void HandleXfer(ulong xferID, uint packetID, byte[] data) {
{ // AssetXferUploader uploaderFound = null;
// AssetXferUploader uploaderFound = null;
lock (XferUploaders)
lock (XferUploaders) {
{ foreach (AssetXferUploader uploader in XferUploaders.Values)
foreach (AssetXferUploader uploader in XferUploaders.Values) {
{ if (uploader.XferID == xferID)
if (uploader.XferID == xferID) {
{ uploader.HandleXferPacket(xferID, packetID, data);
uploader.HandleXferPacket(xferID, packetID, data); break;
break; }
} }
} }
} }
}
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, uint callbackID, string description, string name, sbyte invType,
uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask)
sbyte type, byte wearableType, uint nextOwnerMask) {
{ if (XferUploaders.ContainsKey(transactionID))
if (XferUploaders.ContainsKey(transactionID)) {
{ XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID,
XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID, callbackID, description, name, invType, type,
callbackID, description, name, invType, type, wearableType, nextOwnerMask);
wearableType, nextOwnerMask); }
} }
}
public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, InventoryItemBase item)
InventoryItemBase item) {
{ if (XferUploaders.ContainsKey(transactionID))
if (XferUploaders.ContainsKey(transactionID)) {
{ XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item);
XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item); }
} }
}
/// <summary>
/// <summary> /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed.
/// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed. /// </summary>
/// </summary> /// <param name="transactionID"></param>
/// <param name="transactionID"></param> /// <returns>The asset if the upload has completed, null if it has not.</returns>
/// <returns>The asset if the upload has completed, null if it has not.</returns> public AssetBase GetTransactionAsset(LLUUID transactionID)
public AssetBase GetTransactionAsset(LLUUID transactionID) {
{ if (XferUploaders.ContainsKey(transactionID))
if (XferUploaders.ContainsKey(transactionID)) {
{ AssetXferUploader uploader = XferUploaders[transactionID];
AssetXferUploader uploader = XferUploaders[transactionID]; AssetBase asset = uploader.GetAssetData();
AssetBase asset = uploader.GetAssetData();
lock (XferUploaders)
lock (XferUploaders) {
{ XferUploaders.Remove(transactionID);
XferUploaders.Remove(transactionID); }
}
return asset;
return asset; }
}
return null;
return null; }
}
// Nested Types
// Nested Types public class AssetXferUploader
public class AssetXferUploader {
{ // Fields
// Fields public bool AddToInventory;
public bool AddToInventory; public AssetBase Asset;
public AssetBase Asset; public LLUUID InventFolder = LLUUID.Zero;
public LLUUID InventFolder = LLUUID.Zero; private IClientAPI ourClient;
private IClientAPI ourClient; public LLUUID TransactionID = LLUUID.Zero;
public LLUUID TransactionID = LLUUID.Zero; public bool UploadComplete;
public bool UploadComplete; public ulong XferID;
public ulong XferID; private string m_name = String.Empty;
private string m_name = String.Empty; private string m_description = String.Empty;
private string m_description = String.Empty; private sbyte type = 0;
private sbyte type = 0; private sbyte invType = 0;
private sbyte invType = 0; private byte wearableType = 0;
private byte wearableType = 0; private uint nextPerm = 0;
private uint nextPerm = 0; private bool m_finished = false;
private bool m_finished = false; private bool m_createItem = false;
private bool m_createItem = false; private AgentAssetTransactions m_userTransactions;
private AgentAssetTransactions m_userTransactions; private bool m_storeLocal;
private bool m_storeLocal; private bool m_dumpAssetToFile;
private bool m_dumpAssetToFile;
public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile)
public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile) {
{ m_userTransactions = transactions;
m_userTransactions = transactions; m_dumpAssetToFile = dumpAssetToFile;
m_dumpAssetToFile = dumpAssetToFile; }
}
/// <summary>
/// <summary> /// Process transfer data received from the client.
/// Process transfer data received from the client. /// </summary>
/// </summary> /// <param name="xferID"></param>
/// <param name="xferID"></param> /// <param name="packetID"></param>
/// <param name="packetID"></param> /// <param name="data"></param>
/// <param name="data"></param> /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns>
/// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data)
public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) {
{ if (XferID == xferID)
if (XferID == xferID) {
{ if (Asset.Data.Length > 1)
if (Asset.Data.Length > 1) {
{ byte[] destinationArray = new byte[Asset.Data.Length + data.Length];
byte[] destinationArray = new byte[Asset.Data.Length + data.Length]; Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length);
Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length); Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length);
Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length); Asset.Data = destinationArray;
Asset.Data = destinationArray; }
} else
else {
{ byte[] buffer2 = new byte[data.Length - 4];
byte[] buffer2 = new byte[data.Length - 4]; Array.Copy(data, 4, buffer2, 0, data.Length - 4);
Array.Copy(data, 4, buffer2, 0, data.Length - 4); Asset.Data = buffer2;
Asset.Data = buffer2; }
} ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); newPack.XferID.ID = xferID;
newPack.XferID.ID = xferID; newPack.XferID.Packet = packetID;
newPack.XferID.Packet = packetID; ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); if ((packetID & 0x80000000) != 0)
if ((packetID & 0x80000000) != 0) {
{ SendCompleteMessage();
SendCompleteMessage(); return true;
return true; }
} }
}
return false;
return false; }
}
/// <summary>
/// <summary> /// Initialise asset transfer from the client
/// Initialise asset transfer from the client /// </summary>
/// </summary> /// <param name="xferID"></param>
/// <param name="xferID"></param> /// <param name="packetID"></param>
/// <param name="packetID"></param> /// <param name="data"></param>
/// <param name="data"></param> /// <returns>True if the transfer is complete, false otherwise</returns>
/// <returns>True if the transfer is complete, false otherwise</returns> public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data,
public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, bool storeLocal, bool tempFile)
bool storeLocal, bool tempFile) {
{ ourClient = remoteClient;
ourClient = remoteClient; Asset = new AssetBase();
Asset = new AssetBase(); Asset.FullID = assetID;
Asset.FullID = assetID; Asset.InvType = type;
Asset.InvType = type; Asset.Type = type;
Asset.Type = type; Asset.Data = data;
Asset.Data = data; Asset.Name = "blank";
Asset.Name = "blank"; Asset.Description = "empty";
Asset.Description = "empty"; Asset.Local = storeLocal;
Asset.Local = storeLocal; Asset.Temporary = tempFile;
Asset.Temporary = tempFile;
TransactionID = transaction;
TransactionID = transaction; m_storeLocal = storeLocal;
m_storeLocal = storeLocal; if (Asset.Data.Length > 2)
if (Asset.Data.Length > 2) {
{ SendCompleteMessage();
SendCompleteMessage(); return true;
return true; }
} else
else {
{ RequestStartXfer();
RequestStartXfer(); }
}
return false;
return false; }
}
protected void RequestStartXfer()
protected void RequestStartXfer() {
{ UploadComplete = false;
UploadComplete = false; XferID = Util.GetNextXferID();
XferID = Util.GetNextXferID(); RequestXferPacket newPack = new RequestXferPacket();
RequestXferPacket newPack = new RequestXferPacket(); newPack.XferID.ID = XferID;
newPack.XferID.ID = XferID; newPack.XferID.VFileType = Asset.Type;
newPack.XferID.VFileType = Asset.Type; newPack.XferID.VFileID = Asset.FullID;
newPack.XferID.VFileID = Asset.FullID; newPack.XferID.FilePath = 0;
newPack.XferID.FilePath = 0; newPack.XferID.Filename = new byte[0];
newPack.XferID.Filename = new byte[0]; ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); }
}
protected void SendCompleteMessage()
protected void SendCompleteMessage() {
{ UploadComplete = true;
UploadComplete = true; AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); newPack.AssetBlock.Type = Asset.Type;
newPack.AssetBlock.Type = Asset.Type; newPack.AssetBlock.Success = true;
newPack.AssetBlock.Success = true; newPack.AssetBlock.UUID = Asset.FullID;
newPack.AssetBlock.UUID = Asset.FullID; ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); m_finished = true;
m_finished = true; if (m_createItem)
if (m_createItem) {
{ DoCreateItem();
DoCreateItem(); }
} else if (m_storeLocal)
else if (m_storeLocal) {
{ m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); }
}
// Console.WriteLine("upload complete "+ this.TransactionID);
// Console.WriteLine("upload complete "+ this.TransactionID);
if (m_dumpAssetToFile)
if (m_dumpAssetToFile) {
{ DateTime now = DateTime.Now;
DateTime now = DateTime.Now; string filename =
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,
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);
now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type); SaveAssetToFile(filename, Asset.Data);
SaveAssetToFile(filename, Asset.Data); }
} }
}
///Left this in and commented in case there are unforseen issues
///Left this in and commented in case there are unforseen issues //private void SaveAssetToFile(string filename, byte[] data)
//private void SaveAssetToFile(string filename, byte[] data) //{
//{ // FileStream fs = File.Create(filename);
// FileStream fs = File.Create(filename); // BinaryWriter bw = new BinaryWriter(fs);
// BinaryWriter bw = new BinaryWriter(fs); // bw.Write(data);
// bw.Write(data); // bw.Close();
// bw.Close(); // fs.Close();
// fs.Close(); //}
//} private void SaveAssetToFile(string filename, byte[] data)
private void SaveAssetToFile(string filename, byte[] data) {
{ string assetPath = "UserAssets";
string assetPath = "UserAssets"; if (!Directory.Exists(assetPath))
if (!Directory.Exists(assetPath)) {
{ Directory.CreateDirectory(assetPath);
Directory.CreateDirectory(assetPath); }
} FileStream fs = File.Create(Path.Combine(assetPath, filename));
FileStream fs = File.Create(Path.Combine(assetPath, filename)); BinaryWriter bw = new BinaryWriter(fs);
BinaryWriter bw = new BinaryWriter(fs); bw.Write(data);
bw.Write(data); bw.Close();
bw.Close(); fs.Close();
fs.Close(); }
}
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, uint callbackID, string description, string name, sbyte invType,
uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask)
sbyte type, byte wearableType, uint nextOwnerMask) {
{ if (TransactionID == transactionID)
if (TransactionID == transactionID) {
{ InventFolder = folderID;
InventFolder = folderID; m_name = name;
m_name = name; m_description = description;
m_description = description; this.type = type;
this.type = type; this.invType = invType;
this.invType = invType; this.wearableType = wearableType;
this.wearableType = wearableType; nextPerm = nextOwnerMask;
nextPerm = nextOwnerMask; Asset.Name = name;
Asset.Name = name; Asset.Description = description;
Asset.Description = description; Asset.Type = type;
Asset.Type = type; Asset.InvType = invType;
Asset.InvType = invType; m_createItem = true;
m_createItem = true; if (m_finished)
if (m_finished) {
{ DoCreateItem();
DoCreateItem(); }
} }
} }
}
public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, InventoryItemBase item)
InventoryItemBase item) {
{ if (TransactionID == transactionID)
if (TransactionID == transactionID) {
{ CachedUserInfo userInfo =
CachedUserInfo userInfo = m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(
m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( remoteClient.AgentId);
remoteClient.AgentId);
if (userInfo != null)
if (userInfo != null) {
{ LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId);
LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId);
AssetBase asset
AssetBase asset = m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset(
= m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset( assetID, (item.AssetType == (int) AssetType.Texture ? true : false));
assetID, (item.AssetType == (int) AssetType.Texture ? true : false));
if (asset == null)
if (asset == null) {
{ asset = m_userTransactions.GetTransactionAsset(transactionID);
asset = m_userTransactions.GetTransactionAsset(transactionID); }
}
if (asset != null && asset.FullID == assetID)
if (asset != null && asset.FullID == assetID) {
{ asset.Name = item.Name;
asset.Name = item.Name; asset.Description = item.Description;
asset.Description = item.Description; asset.InvType = (sbyte) item.InvType;
asset.InvType = (sbyte) item.InvType; asset.Type = (sbyte) item.AssetType;
asset.Type = (sbyte) item.AssetType; item.AssetID = asset.FullID;
item.AssetID = asset.FullID;
m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); }
}
userInfo.UpdateItem(remoteClient.AgentId, item);
userInfo.UpdateItem(remoteClient.AgentId, item); }
} }
} }
}
private void DoCreateItem()
private void DoCreateItem() {
{ //really need to fix this call, if lbsa71 saw this he would die.
//really need to fix this call, if lbsa71 saw this he would die. m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); CachedUserInfo userInfo =
CachedUserInfo userInfo = m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId);
m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId); if (userInfo != null)
if (userInfo != null) {
{ InventoryItemBase item = new InventoryItemBase();
InventoryItemBase item = new InventoryItemBase(); item.Owner = ourClient.AgentId;
item.Owner = ourClient.AgentId; item.Creator = ourClient.AgentId;
item.Creator = ourClient.AgentId; item.ID = LLUUID.Random();
item.ID = LLUUID.Random(); item.AssetID = Asset.FullID;
item.AssetID = Asset.FullID; item.Description = m_description;
item.Description = m_description; item.Name = m_name;
item.Name = m_name; item.AssetType = type;
item.AssetType = type; item.InvType = invType;
item.InvType = invType; item.Folder = InventFolder;
item.Folder = InventFolder; item.BasePermissions = 2147483647;
item.BasePermissions = 2147483647; item.CurrentPermissions = 2147483647;
item.CurrentPermissions = 2147483647; item.NextPermissions = nextPerm;
item.NextPermissions = nextPerm; item.Flags = (uint)wearableType;
item.Flags = (uint)wearableType;
userInfo.AddItem(ourClient.AgentId, item);
userInfo.AddItem(ourClient.AgentId, item); ourClient.SendInventoryItemCreateUpdate(item);
ourClient.SendInventoryItemCreateUpdate(item); }
} }
}
public AssetBase GetAssetData()
public AssetBase GetAssetData() {
{ if (m_finished)
if (m_finished) {
{ return Asset;
return Asset; }
} return null;
return null; }
} }
} }
} }
}

View File

@ -1,286 +1,286 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using libsecondlife; using libsecondlife;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Modules.Agent.AssetTransaction;
using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules
{ namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction
public class AgentAssetTransactionModule : IRegionModule, IAgentAssetTransactions {
{ public class AssetTransactionModule : IRegionModule, IAgentAssetTransactions
private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>(); {
private Scene m_scene = null; private readonly Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
private bool m_dumpAssetsToFile = false; private Scene m_scene = null;
private bool m_dumpAssetsToFile = false;
private AgentAssetTransactionsManager m_transactionManager;
private AgentAssetTransactionsManager m_transactionManager;
public AgentAssetTransactionModule()
{ public AssetTransactionModule()
// System.Console.WriteLine("creating AgentAssetTransactionModule"); {
} // System.Console.WriteLine("creating AgentAssetTransactionModule");
}
public void Initialise(Scene scene, IConfigSource config)
{ public void Initialise(Scene scene, IConfigSource config)
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) {
{ if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
// System.Console.WriteLine("initialising AgentAssetTransactionModule"); {
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); // System.Console.WriteLine("initialising AgentAssetTransactionModule");
scene.RegisterModuleInterface<IAgentAssetTransactions>(this); RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
scene.RegisterModuleInterface<IAgentAssetTransactions>(this);
scene.EventManager.OnNewClient += NewClient;
} scene.EventManager.OnNewClient += NewClient;
}
if (m_scene == null)
{ if (m_scene == null)
m_scene = scene; {
if (config.Configs["StandAlone"] != null) m_scene = scene;
{ if (config.Configs["StandAlone"] != null)
try {
{ try
m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false); {
m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile); m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false);
} m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile);
catch (Exception) }
{ catch (Exception)
m_transactionManager = new AgentAssetTransactionsManager(m_scene, false); {
} m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
} }
else }
{ else
m_transactionManager = new AgentAssetTransactionsManager(m_scene, false); {
} m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
}
}
} }
}
public void PostInitialise()
{ public void PostInitialise()
{
}
}
public void Close()
{ public void Close()
} {
}
public string Name
{ public string Name
get { return "AgentTransactionModule"; } {
} get { return "AgentTransactionModule"; }
}
public bool IsSharedModule
{ public bool IsSharedModule
get { return true; } {
} get { return true; }
}
public void NewClient(IClientAPI client)
{ public void NewClient(IClientAPI client)
client.OnAssetUploadRequest += m_transactionManager.HandleUDPUploadRequest; {
client.OnXferReceive += m_transactionManager.HandleXfer; 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, public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
sbyte type, byte wearableType, uint nextOwnerMask) 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); {
} m_transactionManager.HandleItemCreationFromTransaction(remoteClient, transactionID, folderID, callbackID, description, name, invType, type, wearableType, nextOwnerMask);
}
public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
InventoryItemBase item) public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
{ InventoryItemBase item)
m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); {
} m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
}
public void RemoveAgentAssetTransactions(LLUUID userID)
{ public void RemoveAgentAssetTransactions(LLUUID userID)
m_transactionManager.RemoveAgentAssetTransactions(userID); {
} m_transactionManager.RemoveAgentAssetTransactions(userID);
} }
}
//should merge this classes and clean up
public class AgentAssetTransactionsManager public class AgentAssetTransactionsManager
{ {
private static readonly ILog m_log private static readonly ILog m_log
= LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// Fields // Fields
public Scene MyScene; public Scene MyScene;
/// <summary> /// <summary>
/// Each agent has its own singleton collection of transactions /// Each agent has its own singleton collection of transactions
/// </summary> /// </summary>
private Dictionary<LLUUID, AgentAssetTransactions> AgentTransactions = private Dictionary<LLUUID, AgentAssetTransactions> AgentTransactions =
new Dictionary<LLUUID, AgentAssetTransactions>(); new Dictionary<LLUUID, AgentAssetTransactions>();
/// <summary> /// <summary>
/// Should we dump uploaded assets to the filesystem? /// Should we dump uploaded assets to the filesystem?
/// </summary> /// </summary>
private bool m_dumpAssetsToFile; private bool m_dumpAssetsToFile;
public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile) public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile)
{ {
MyScene = scene; MyScene = scene;
m_dumpAssetsToFile = dumpAssetsToFile; m_dumpAssetsToFile = dumpAssetsToFile;
} }
/// <summary> /// <summary>
/// Get the collection of asset transactions for the given user. If one does not already exist, it /// Get the collection of asset transactions for the given user. If one does not already exist, it
/// is created. /// is created.
/// </summary> /// </summary>
/// <param name="userID"></param> /// <param name="userID"></param>
/// <returns></returns> /// <returns></returns>
private AgentAssetTransactions GetUserTransactions(LLUUID userID) private AgentAssetTransactions GetUserTransactions(LLUUID userID)
{ {
lock (AgentTransactions) lock (AgentTransactions)
{ {
if (!AgentTransactions.ContainsKey(userID)) if (!AgentTransactions.ContainsKey(userID))
{ {
AgentAssetTransactions transactions AgentAssetTransactions transactions
= new AgentAssetTransactions(userID, this, m_dumpAssetsToFile); = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile);
AgentTransactions.Add(userID, transactions); AgentTransactions.Add(userID, transactions);
} }
return AgentTransactions[userID]; return AgentTransactions[userID];
} }
} }
/// <summary> /// <summary>
/// Remove the given agent asset transactions. This should be called when a client is departing /// 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). /// from a scene (and hence won't be making any more transactions here).
/// </summary> /// </summary>
/// <param name="userID"></param> /// <param name="userID"></param>
public void RemoveAgentAssetTransactions(LLUUID userID) public void RemoveAgentAssetTransactions(LLUUID userID)
{ {
// m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID);
lock (AgentTransactions) lock (AgentTransactions)
{ {
AgentTransactions.Remove(userID); AgentTransactions.Remove(userID);
} }
} }
/// <summary> /// <summary>
/// Create an inventory item from data that has been received through a transaction. /// 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 /// This is called when new clothing or body parts are created. It may also be called in other
/// situations. /// situations.
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="transactionID"></param> /// <param name="transactionID"></param>
/// <param name="folderID"></param> /// <param name="folderID"></param>
/// <param name="callbackID"></param> /// <param name="callbackID"></param>
/// <param name="description"></param> /// <param name="description"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="invType"></param> /// <param name="invType"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="wearableType"></param> /// <param name="wearableType"></param>
/// <param name="nextOwnerMask"></param> /// <param name="nextOwnerMask"></param>
public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
uint callbackID, string description, string name, sbyte invType, uint callbackID, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask) sbyte type, byte wearableType, uint nextOwnerMask)
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name);
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
transactions.RequestCreateInventoryItem( transactions.RequestCreateInventoryItem(
remoteClient, transactionID, folderID, callbackID, description, remoteClient, transactionID, folderID, callbackID, description,
name, invType, type, wearableType, nextOwnerMask); name, invType, type, wearableType, nextOwnerMask);
} }
/// <summary> /// <summary>
/// Update an inventory item with data that has been received through a transaction. /// 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 /// 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. /// colours). It may also be called in other situations.
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="transactionID"></param> /// <param name="transactionID"></param>
/// <param name="item"></param> /// <param name="item"></param>
public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
InventoryItemBase item) InventoryItemBase item)
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}",
item.Name); item.Name);
AgentAssetTransactions transactions AgentAssetTransactions transactions
= GetUserTransactions(remoteClient.AgentId); = GetUserTransactions(remoteClient.AgentId);
transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
} }
/// <summary> /// <summary>
/// Request that a client (agent) begin an asset transfer. /// Request that a client (agent) begin an asset transfer.
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="assetID"></param> /// <param name="assetID"></param>
/// <param name="transaction"></param> /// <param name="transaction"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="data"></param></param> /// <param name="data"></param></param>
/// <param name="tempFile"></param> /// <param name="tempFile"></param>
public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type,
byte[] data, bool storeLocal, bool tempFile) byte[] data, bool storeLocal, bool tempFile)
{ {
// Console.WriteLine("asset upload of " + assetID); // Console.WriteLine("asset upload of " + assetID);
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction); AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
if (uploader != null) if (uploader != null)
{ {
if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile)) if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile))
{ {
} }
} }
} }
/// <summary> /// <summary>
/// Handle asset transfer data packets received in response to the asset upload request in /// Handle asset transfer data packets received in response to the asset upload request in
/// HandleUDPUploadRequest() /// HandleUDPUploadRequest()
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="xferID"></param> /// <param name="xferID"></param>
/// <param name="packetID"></param> /// <param name="packetID"></param>
/// <param name="data"></param> /// <param name="data"></param>
public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
{ {
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
transactions.HandleXfer(xferID, packetID, data); transactions.HandleXfer(xferID, packetID, data);
} }
} }
} }

View File

@ -1,218 +1,215 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using libsecondlife; using libsecondlife;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
{ {
//this is a first attempt, to start breaking the mess thats called the assetcache up. public class TextureDownloadModule : IRegionModule
// basically this should be the texture sending (to clients) code moved out of assetcache {
//and some small clean up //private static readonly log4net.ILog m_log
public class TextureDownloadModule : IRegionModule // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
{
//private static readonly log4net.ILog m_log private Scene m_scene;
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private List<Scene> m_scenes = new List<Scene>();
private Scene m_scene; /// <summary>
private List<Scene> m_scenes = new List<Scene>(); /// There is one queue for all textures waiting to be sent, regardless of the requesting user.
/// </summary>
/// <summary> private readonly BlockingQueue<ITextureSender> m_queueSenders
/// There is one queue for all textures waiting to be sent, regardless of the requesting user. = new BlockingQueue<ITextureSender>();
/// </summary>
private readonly BlockingQueue<ITextureSender> m_queueSenders /// <summary>
= new BlockingQueue<ITextureSender>(); /// Each user has their own texture download service.
/// </summary>
/// <summary> private readonly Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices =
/// Each user has their own texture download service. new Dictionary<LLUUID, UserTextureDownloadService>();
/// </summary>
private readonly Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices = private Thread m_thread;
new Dictionary<LLUUID, UserTextureDownloadService>();
public TextureDownloadModule()
private Thread m_thread; {
}
public TextureDownloadModule()
{ public void Initialise(Scene scene, IConfigSource config)
} {
if (m_scene == null)
public void Initialise(Scene scene, IConfigSource config) {
{ //Console.WriteLine("Creating Texture download module");
if (m_scene == null) m_thread = new Thread(new ThreadStart(ProcessTextureSenders));
{ m_thread.Name = "ProcessTextureSenderThread";
//Console.WriteLine("Creating Texture download module"); m_thread.IsBackground = true;
m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); m_thread.Start();
m_thread.Name = "ProcessTextureSenderThread"; ThreadTracker.Add(m_thread);
m_thread.IsBackground = true; }
m_thread.Start();
ThreadTracker.Add(m_thread); if (!m_scenes.Contains(scene))
} {
m_scenes.Add(scene);
if (!m_scenes.Contains(scene)) m_scene = scene;
{ m_scene.EventManager.OnNewClient += NewClient;
m_scenes.Add(scene); m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence;
m_scene = scene; }
m_scene.EventManager.OnNewClient += NewClient; }
m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence;
} /// <summary>
} /// Cleanup the texture service related objects for the removed presence.
/// </summary>
/// <summary> /// <param name="agentId"> </param>
/// Cleanup the texture service related objects for the removed presence. private void EventManager_OnRemovePresence(LLUUID agentId)
/// </summary> {
/// <param name="agentId"> </param> UserTextureDownloadService textureService;
private void EventManager_OnRemovePresence(LLUUID agentId)
{ lock (m_userTextureServices)
UserTextureDownloadService textureService; {
if (m_userTextureServices.TryGetValue(agentId, out textureService))
lock (m_userTextureServices) {
{ textureService.Close();
if (m_userTextureServices.TryGetValue(agentId, out textureService))
{ m_userTextureServices.Remove(agentId);
textureService.Close(); }
}
m_userTextureServices.Remove(agentId); }
}
} public void PostInitialise()
} {
}
public void PostInitialise()
{ public void Close()
} {
}
public void Close()
{ public string Name
} {
get { return "TextureDownloadModule"; }
public string Name }
{
get { return "TextureDownloadModule"; } public bool IsSharedModule
} {
get { return false; }
public bool IsSharedModule }
{
get { return false; } public void NewClient(IClientAPI client)
} {
client.OnRequestTexture += TextureRequest;
public void NewClient(IClientAPI client) }
{
client.OnRequestTexture += TextureRequest; /// <summary>
} /// Does this user have a registered texture download service?
/// </summary>
/// <summary> /// <param name="userID"></param>
/// Does this user have a registered texture download service? /// <param name="textureService"></param>
/// </summary> /// <returns>Always returns true, since a service is created if one does not already exist</returns>
/// <param name="userID"></param> private bool TryGetUserTextureService(
/// <param name="textureService"></param> IClientAPI client, out UserTextureDownloadService textureService)
/// <returns>Always returns true, since a service is created if one does not already exist</returns> {
private bool TryGetUserTextureService( lock (m_userTextureServices)
IClientAPI client, out UserTextureDownloadService textureService) {
{ if (m_userTextureServices.TryGetValue(client.AgentId, out textureService))
lock (m_userTextureServices) {
{ return true;
if (m_userTextureServices.TryGetValue(client.AgentId, out textureService)) }
{
return true; textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders);
} m_userTextureServices.Add(client.AgentId, textureService);
textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders); return true;
m_userTextureServices.Add(client.AgentId, textureService); }
}
return true;
} /// <summary>
} /// Start the process of requesting a given texture.
/// </summary>
/// <summary> /// <param name="sender"> </param>
/// Start the process of requesting a given texture. /// <param name="e"></param>
/// </summary> public void TextureRequest(Object sender, TextureRequestArgs e)
/// <param name="sender"> </param> {
/// <param name="e"></param> IClientAPI client = (IClientAPI) sender;
public void TextureRequest(Object sender, TextureRequestArgs e) UserTextureDownloadService textureService;
{
IClientAPI client = (IClientAPI) sender; if (TryGetUserTextureService(client, out textureService))
UserTextureDownloadService textureService; {
textureService.HandleTextureRequest(e);
if (TryGetUserTextureService(client, out textureService)) }
{ }
textureService.HandleTextureRequest(e);
} /// <summary>
} /// Entry point for the thread dedicated to processing the texture queue.
/// </summary>
/// <summary> public void ProcessTextureSenders()
/// Entry point for the thread dedicated to processing the texture queue. {
/// </summary> ITextureSender sender = null;
public void ProcessTextureSenders()
{ while (true)
ITextureSender sender = null; {
sender = m_queueSenders.Dequeue();
while (true)
{ if (sender.Cancel)
sender = m_queueSenders.Dequeue(); {
TextureSent(sender);
if (sender.Cancel)
{ sender.Cancel = false;
TextureSent(sender); }
else
sender.Cancel = false; {
} bool finished = sender.SendTexturePacket();
else if (finished)
{ {
bool finished = sender.SendTexturePacket(); TextureSent(sender);
if (finished) }
{ else
TextureSent(sender); {
} m_queueSenders.Enqueue(sender);
else }
{ }
m_queueSenders.Enqueue(sender);
} // Make sure that any sender we currently have can get garbage collected
} sender = null;
// Make sure that any sender we currently have can get garbage collected //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count());
sender = null; }
}
//m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count());
} /// <summary>
} /// Called when the texture has finished sending.
/// </summary>
/// <summary> /// <param name="sender"></param>
/// Called when the texture has finished sending. private void TextureSent(ITextureSender sender)
/// </summary> {
/// <param name="sender"></param> sender.Sending = false;
private void TextureSent(ITextureSender sender) //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID);
{ m_scene.AddPendingDownloads(-1);
sender.Sending = false; }
//m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID); }
m_scene.AddPendingDownloads(-1); }
}
}
}

View File

@ -1,93 +1,93 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using libsecondlife; using libsecondlife;
using libsecondlife.Packets; using libsecondlife.Packets;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
{ {
/// <summary> /// <summary>
/// Sends a 'texture not found' packet back to the client /// Sends a 'texture not found' packet back to the client
/// </summary> /// </summary>
public class TextureNotFoundSender : ITextureSender public class TextureNotFoundSender : ITextureSender
{ {
//private static readonly log4net.ILog m_log //private static readonly log4net.ILog m_log
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private LLUUID m_textureId; private LLUUID m_textureId;
private IClientAPI m_client; private IClientAPI m_client;
// See ITextureSender // See ITextureSender
public bool Sending public bool Sending
{ {
get { return false; } get { return false; }
set { m_sending = value; } set { m_sending = value; }
} }
private bool m_sending = false; private bool m_sending = false;
// See ITextureSender // See ITextureSender
public bool Cancel public bool Cancel
{ {
get { return false; } get { return false; }
set { m_cancel = value; } set { m_cancel = value; }
} }
private bool m_cancel = false; private bool m_cancel = false;
public TextureNotFoundSender(IClientAPI client, LLUUID textureID) public TextureNotFoundSender(IClientAPI client, LLUUID textureID)
{ {
m_client = client; m_client = client;
m_textureId = textureID; m_textureId = textureID;
} }
// See ITextureSender // See ITextureSender
public void UpdateRequest(int discardLevel, uint packetNumber) public void UpdateRequest(int discardLevel, uint packetNumber)
{ {
// Not need to implement since priority changes don't affect this operation // Not need to implement since priority changes don't affect this operation
} }
// See ITextureSender // See ITextureSender
public bool SendTexturePacket() public bool SendTexturePacket()
{ {
//m_log.InfoFormat( //m_log.InfoFormat(
// "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found", // "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found",
// m_textureId); // m_textureId);
ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket(); ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket();
notFound.ImageID.ID = m_textureId; notFound.ImageID.ID = m_textureId;
// XXX Temporarily disabling as this appears to be causing client crashes on at least // XXX Temporarily disabling as this appears to be causing client crashes on at least
// 1.19.0(5) of the Linden Second Life client. // 1.19.0(5) of the Linden Second Life client.
// m_client.OutPacket(notFound, ThrottleOutPacketType.Texture); // m_client.OutPacket(notFound, ThrottleOutPacketType.Texture);
return true; return true;
} }
} }
} }

View File

@ -1,250 +1,252 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using libsecondlife; using libsecondlife;
using log4net; using log4net;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications.Limit; using OpenSim.Framework.Communications.Limit;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Modules.Agent.TextureDownload;
using OpenSim.Region.Environment.Modules.Agent.TextureSender;
namespace OpenSim.Region.Environment.Modules using OpenSim.Region.Environment.Scenes;
{
/// <summary> 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 /// <summary>
/// asset cache). /// This module sets up texture senders in response to client texture requests, and places them on a
/// </summary> /// processing queue once those senders have the appropriate data (i.e. a texture retrieved from the
public class UserTextureDownloadService /// asset cache).
{ /// </summary>
private static readonly ILog m_log public class UserTextureDownloadService
= LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); {
private static readonly ILog m_log
/// <summary> = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// We will allow the client to request the same texture n times before dropping further requests
/// /// <summary>
/// This number includes repeated requests for the same texture at different resolutions (which we don't /// We will allow the client to request the same texture n times before dropping further requests
/// currently handle properly as far as I know). However, this situation should be handled in a more ///
/// sophisticated way. /// This number includes repeated requests for the same texture at different resolutions (which we don't
/// </summary> /// currently handle properly as far as I know). However, this situation should be handled in a more
private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5; /// sophisticated way.
/// </summary>
/// <summary> 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 /// <summary>
/// the same missing textures /// We're going to limit requests for the same missing texture.
/// </summary> /// XXX This is really a temporary solution to deal with the situation where a client continually requests
private readonly IRequestLimitStrategy<LLUUID> missingTextureLimitStrategy /// the same missing textures
= new RepeatLimitStrategy<LLUUID>(MAX_ALLOWED_TEXTURE_REQUESTS); /// </summary>
private readonly IRequestLimitStrategy<LLUUID> missingTextureLimitStrategy
/// <summary> = new RepeatLimitStrategy<LLUUID>(MAX_ALLOWED_TEXTURE_REQUESTS);
/// XXX Also going to limit requests for found textures.
/// </summary> /// <summary>
private readonly IRequestLimitStrategy<LLUUID> foundTextureLimitStrategy /// XXX Also going to limit requests for found textures.
= new RepeatLimitStrategy<LLUUID>(MAX_ALLOWED_TEXTURE_REQUESTS); /// </summary>
private readonly IRequestLimitStrategy<LLUUID> foundTextureLimitStrategy
/// <summary> = new RepeatLimitStrategy<LLUUID>(MAX_ALLOWED_TEXTURE_REQUESTS);
/// Holds texture senders before they have received the appropriate texture from the asset cache.
/// </summary> /// <summary>
private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>(); /// Holds texture senders before they have received the appropriate texture from the asset cache.
/// </summary>
/// <summary> private readonly Dictionary<LLUUID, TextureSender.TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender.TextureSender>();
/// Texture Senders are placed in this queue once they have received their texture from the asset
/// cache. Another module actually invokes the send. /// <summary>
/// </summary> /// Texture Senders are placed in this queue once they have received their texture from the asset
private readonly BlockingQueue<ITextureSender> m_sharedSendersQueue; /// cache. Another module actually invokes the send.
/// </summary>
private readonly Scene m_scene; private readonly BlockingQueue<ITextureSender> m_sharedSendersQueue;
private readonly IClientAPI m_client; private readonly Scene m_scene;
public UserTextureDownloadService( private readonly IClientAPI m_client;
IClientAPI client, Scene scene, BlockingQueue<ITextureSender> sharedQueue)
{ public UserTextureDownloadService(
m_client = client; IClientAPI client, Scene scene, BlockingQueue<ITextureSender> sharedQueue)
m_scene = scene; {
m_sharedSendersQueue = sharedQueue; m_client = client;
} m_scene = scene;
m_sharedSendersQueue = sharedQueue;
/// <summary> }
/// Handle a texture request. This involves creating a texture sender and placing it on the
/// previously passed in shared queue. /// <summary>
/// </summary> /// Handle a texture request. This involves creating a texture sender and placing it on the
/// <param name="e"></param> /// previously passed in shared queue.
public void HandleTextureRequest(TextureRequestArgs e) /// </summary>
{ /// <param name="e"></param>
TextureSender textureSender; public void HandleTextureRequest(TextureRequestArgs e)
{
//TODO: should be working out the data size/ number of packets to be sent for each discard level TextureSender.TextureSender textureSender;
if ((e.DiscardLevel >= 0) || (e.Priority != 0))
{ //TODO: should be working out the data size/ number of packets to be sent for each discard level
lock (m_textureSenders) if ((e.DiscardLevel >= 0) || (e.Priority != 0))
{ {
if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) lock (m_textureSenders)
{ {
// If we've received new non UUID information for this request and it hasn't dispatched if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
// yet, then update the request accordingly. {
textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); // If we've received new non UUID information for this request and it hasn't dispatched
} // yet, then update the request accordingly.
else textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
{ }
if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) else
{ {
// m_log.DebugFormat( if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID))
// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}", {
// e.RequestedAssetID, m_client.AgentId); // m_log.DebugFormat(
// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}",
return; // e.RequestedAssetID, m_client.AgentId);
}
else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) return;
{ }
if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID)) else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID))
{ {
// Commenting out this message for now as it causes too much noise with other if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID))
// debug messages. {
// TODO: possibly record this as a statistic in the future // Commenting out this message for now as it causes too much noise with other
// // debug messages.
// m_log.DebugFormat( // TODO: possibly record this as a statistic in the future
// "[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); // 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; }
}
return;
m_scene.AddPendingDownloads(1); }
TextureSender requestHandler = new TextureSender(m_client, e.DiscardLevel, e.PacketNumber); m_scene.AddPendingDownloads(1);
m_textureSenders.Add(e.RequestedAssetID, requestHandler);
TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber);
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); m_textureSenders.Add(e.RequestedAssetID, requestHandler);
}
} m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true);
} }
else }
{ }
lock (m_textureSenders) else
{ {
if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) lock (m_textureSenders)
{ {
textureSender.Cancel = true; if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
} {
} textureSender.Cancel = true;
} }
} }
}
/// <summary> }
/// The callback for the asset cache when a texture has been retrieved. This method queues the
/// texture sender for processing. /// <summary>
/// </summary> /// The callback for the asset cache when a texture has been retrieved. This method queues the
/// <param name="textureID"></param> /// texture sender for processing.
/// <param name="texture"></param> /// </summary>
public void TextureCallback(LLUUID textureID, AssetBase texture) /// <param name="textureID"></param>
{ /// <param name="texture"></param>
//m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false)); public void TextureCallback(LLUUID textureID, AssetBase texture)
{
lock (m_textureSenders) //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false));
{
TextureSender textureSender; lock (m_textureSenders)
{
if (m_textureSenders.TryGetValue(textureID, out textureSender)) TextureSender.TextureSender textureSender;
{
// XXX It may be perfectly valid for a texture to have no data... but if we pass if (m_textureSenders.TryGetValue(textureID, out textureSender))
// this on to the TextureSender it will blow up, so just discard for now. {
// Needs investigation. // XXX It may be perfectly valid for a texture to have no data... but if we pass
if (texture == null || texture.Data == null) // this on to the TextureSender it will blow up, so just discard for now.
{ // Needs investigation.
if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID)) if (texture == null || texture.Data == null)
{ {
missingTextureLimitStrategy.MonitorRequests(textureID); if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID))
{
m_log.DebugFormat( missingTextureLimitStrategy.MonitorRequests(textureID);
"[USER TEXTURE DOWNLOAD SERVICE]: Queueing first TextureNotFoundSender for {0}, client {1}",
textureID, m_client.AgentId); 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);
} ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID);
else EnqueueTextureSender(textureNotFoundSender);
{ }
if (!textureSender.ImageLoaded) else
{ {
textureSender.TextureReceived(texture); if (!textureSender.ImageLoaded)
EnqueueTextureSender(textureSender); {
textureSender.TextureReceived(texture);
foundTextureLimitStrategy.MonitorRequests(textureID); 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); //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID);
} m_textureSenders.Remove(textureID);
else //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count);
{ }
m_log.WarnFormat( else
"Got a texture uuid {0} with no sender object to handle it, this shouldn't happen", {
textureID); m_log.WarnFormat(
} "Got a texture uuid {0} with no sender object to handle it, this shouldn't happen",
} textureID);
} }
}
/// <summary> }
/// Place a ready texture sender on the processing queue.
/// </summary> /// <summary>
/// <param name="textureSender"></param> /// Place a ready texture sender on the processing queue.
private void EnqueueTextureSender(ITextureSender textureSender) /// </summary>
{ /// <param name="textureSender"></param>
textureSender.Cancel = false; private void EnqueueTextureSender(ITextureSender textureSender)
textureSender.Sending = true; {
textureSender.Cancel = false;
if (!m_sharedSendersQueue.Contains(textureSender)) textureSender.Sending = true;
{
m_sharedSendersQueue.Enqueue(textureSender); if (!m_sharedSendersQueue.Contains(textureSender))
} {
} m_sharedSendersQueue.Enqueue(textureSender);
}
/// <summary> }
/// Close this module.
/// </summary> /// <summary>
internal void Close() /// Close this module.
{ /// </summary>
lock (m_textureSenders) internal void Close()
{ {
foreach( TextureSender textureSender in m_textureSenders.Values ) lock (m_textureSenders)
{ {
textureSender.Cancel = true; foreach( TextureSender.TextureSender textureSender in m_textureSenders.Values )
} {
textureSender.Cancel = true;
m_textureSenders.Clear(); }
}
} m_textureSenders.Clear();
} }
} }
}
}

View File

@ -1,220 +1,220 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Reflection; using System.Reflection;
using libsecondlife.Packets; using libsecondlife.Packets;
using log4net; using log4net;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
{ {
/// <summary> /// <summary>
/// A TextureSender handles the process of receiving a texture requested by the client from the /// 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. /// AssetCache, and then sending that texture back to the client.
/// </summary> /// </summary>
public class TextureSender : ITextureSender public class TextureSender : ITextureSender
{ {
private static readonly ILog m_log private static readonly ILog m_log
= LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary> /// <summary>
/// Records the number of times texture send has been called. /// Records the number of times texture send has been called.
/// </summary> /// </summary>
public int counter = 0; public int counter = 0;
/// <summary> /// <summary>
/// Holds the texture asset to send. /// Holds the texture asset to send.
/// </summary> /// </summary>
private AssetBase m_asset; private AssetBase m_asset;
//public LLUUID assetID { get { return m_asset.FullID; } } //public LLUUID assetID { get { return m_asset.FullID; } }
/// <summary> /// <summary>
/// This is actually the number of extra packets required to send the texture data! We always assume /// This is actually the number of extra packets required to send the texture data! We always assume
/// at least one is required. /// at least one is required.
/// </summary> /// </summary>
private int NumPackets = 0; private int NumPackets = 0;
/// <summary> /// <summary>
/// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts /// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts
/// at the 600th byte (0th indexed). /// at the 600th byte (0th indexed).
/// </summary> /// </summary>
private int PacketCounter = 0; private int PacketCounter = 0;
// See ITextureSender // See ITextureSender
public bool Cancel public bool Cancel
{ {
get { return false; } get { return false; }
set { m_cancel = value; } set { m_cancel = value; }
} }
private bool m_cancel = false; private bool m_cancel = false;
// See ITextureSender // See ITextureSender
public bool Sending public bool Sending
{ {
get { return false; } get { return false; }
set { m_sending = value; } set { m_sending = value; }
} }
private bool m_sending = false; private bool m_sending = false;
public bool ImageLoaded = false; public bool ImageLoaded = false;
private IClientAPI RequestUser; private IClientAPI RequestUser;
private int RequestedDiscardLevel = -1; private int RequestedDiscardLevel = -1;
private uint StartPacketNumber = 0; private uint StartPacketNumber = 0;
public TextureSender(IClientAPI client, int discardLevel, uint packetNumber) public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
{ {
RequestUser = client; RequestUser = client;
RequestedDiscardLevel = discardLevel; RequestedDiscardLevel = discardLevel;
StartPacketNumber = packetNumber; StartPacketNumber = packetNumber;
} }
/// <summary> /// <summary>
/// Load up the texture data to send. /// Load up the texture data to send.
/// </summary> /// </summary>
/// <param name="asset"> /// <param name="asset">
/// A <see cref="AssetBase"/> /// A <see cref="AssetBase"/>
/// </param> /// </param>
public void TextureReceived(AssetBase asset) public void TextureReceived(AssetBase asset)
{ {
m_asset = asset; m_asset = asset;
NumPackets = CalculateNumPackets(asset.Data.Length); NumPackets = CalculateNumPackets(asset.Data.Length);
PacketCounter = (int) StartPacketNumber; PacketCounter = (int) StartPacketNumber;
ImageLoaded = true; ImageLoaded = true;
} }
// See ITextureSender // See ITextureSender
public void UpdateRequest(int discardLevel, uint packetNumber) public void UpdateRequest(int discardLevel, uint packetNumber)
{ {
RequestedDiscardLevel = discardLevel; RequestedDiscardLevel = discardLevel;
StartPacketNumber = packetNumber; StartPacketNumber = packetNumber;
PacketCounter = (int) StartPacketNumber; PacketCounter = (int) StartPacketNumber;
} }
// See ITextureSender // See ITextureSender
public bool SendTexturePacket() public bool SendTexturePacket()
{ {
//m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID); //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID);
SendPacket(); SendPacket();
counter++; counter++;
if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1))))) ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1)))))
{ {
return true; return true;
} }
return false; return false;
} }
/// <summary> /// <summary>
/// Sends a texture packet to the client. /// Sends a texture packet to the client.
/// </summary> /// </summary>
private void SendPacket() private void SendPacket()
{ {
if (PacketCounter <= NumPackets) if (PacketCounter <= NumPackets)
{ {
if (PacketCounter == 0) if (PacketCounter == 0)
{ {
if (NumPackets == 0) if (NumPackets == 0)
{ {
ImageDataPacket im = new ImageDataPacket(); ImageDataPacket im = new ImageDataPacket();
im.Header.Reliable = false; im.Header.Reliable = false;
im.ImageID.Packets = 1; im.ImageID.Packets = 1;
im.ImageID.ID = m_asset.FullID; im.ImageID.ID = m_asset.FullID;
im.ImageID.Size = (uint) m_asset.Data.Length; im.ImageID.Size = (uint) m_asset.Data.Length;
im.ImageData.Data = m_asset.Data; im.ImageData.Data = m_asset.Data;
im.ImageID.Codec = 2; im.ImageID.Codec = 2;
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
PacketCounter++; PacketCounter++;
} }
else else
{ {
ImageDataPacket im = new ImageDataPacket(); ImageDataPacket im = new ImageDataPacket();
im.Header.Reliable = false; im.Header.Reliable = false;
im.ImageID.Packets = (ushort) (NumPackets); im.ImageID.Packets = (ushort) (NumPackets);
im.ImageID.ID = m_asset.FullID; im.ImageID.ID = m_asset.FullID;
im.ImageID.Size = (uint) m_asset.Data.Length; im.ImageID.Size = (uint) m_asset.Data.Length;
im.ImageData.Data = new byte[600]; im.ImageData.Data = new byte[600];
Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600);
im.ImageID.Codec = 2; im.ImageID.Codec = 2;
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
PacketCounter++; PacketCounter++;
} }
} }
else else
{ {
ImagePacketPacket im = new ImagePacketPacket(); ImagePacketPacket im = new ImagePacketPacket();
im.Header.Reliable = false; im.Header.Reliable = false;
im.ImageID.Packet = (ushort) (PacketCounter); im.ImageID.Packet = (ushort) (PacketCounter);
im.ImageID.ID = m_asset.FullID; im.ImageID.ID = m_asset.FullID;
int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1)); int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1));
if (size > 1000) size = 1000; if (size > 1000) size = 1000;
im.ImageData.Data = new byte[size]; im.ImageData.Data = new byte[size];
try try
{ {
Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size); Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size);
} }
catch (ArgumentOutOfRangeException) catch (ArgumentOutOfRangeException)
{ {
m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" + m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
m_asset.FullID.ToString() ); m_asset.FullID.ToString() );
return; return;
} }
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
PacketCounter++; PacketCounter++;
} }
} }
} }
/// <summary> /// <summary>
/// Calculate the number of packets that will be required to send the texture loaded into this sender /// 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... /// This is actually the number of 1000 byte packets not including an initial 600 byte packet...
/// </summary> /// </summary>
/// <param name="length"></param> /// <param name="length"></param>
/// <returns></returns> /// <returns></returns>
private int CalculateNumPackets(int length) private int CalculateNumPackets(int length)
{ {
int numPackets = 0; int numPackets = 0;
if (length > 600) if (length > 600)
{ {
//over 600 bytes so split up file //over 600 bytes so split up file
int restData = (length - 600); int restData = (length - 600);
int restPackets = ((restData + 999)/1000); int restPackets = ((restData + 999)/1000);
numPackets = restPackets; numPackets = restPackets;
} }
return numPackets; return numPackets;
} }
} }
} }

View File

@ -1,225 +1,225 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using libsecondlife; using libsecondlife;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Agent.Xfer
{ {
public class XferModule : IRegionModule, IXfer public class XferModule : IRegionModule, IXfer
{ {
public Dictionary<string, byte[]> NewFiles = new Dictionary<string, byte[]>(); public Dictionary<string, byte[]> NewFiles = new Dictionary<string, byte[]>();
public Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>(); public Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>();
private Scene m_scene; private Scene m_scene;
public XferModule() public XferModule()
{ {
} }
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
m_scene = scene; m_scene = scene;
m_scene.EventManager.OnNewClient += NewClient; m_scene.EventManager.OnNewClient += NewClient;
m_scene.RegisterModuleInterface<IXfer>(this); m_scene.RegisterModuleInterface<IXfer>(this);
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "XferModule"; } get { return "XferModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return false; } get { return false; }
} }
public void NewClient(IClientAPI client) public void NewClient(IClientAPI client)
{ {
client.OnRequestXfer += RequestXfer; client.OnRequestXfer += RequestXfer;
client.OnConfirmXfer += AckPacket; client.OnConfirmXfer += AckPacket;
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="xferID"></param> /// <param name="xferID"></param>
/// <param name="fileName"></param> /// <param name="fileName"></param>
public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName) public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName)
{ {
lock (NewFiles) lock (NewFiles)
{ {
if (NewFiles.ContainsKey(fileName)) if (NewFiles.ContainsKey(fileName))
{ {
if (!Transfers.ContainsKey(xferID)) if (!Transfers.ContainsKey(xferID))
{ {
byte[] fileData = NewFiles[fileName]; byte[] fileData = NewFiles[fileName];
XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
Transfers.Add(xferID, transaction); Transfers.Add(xferID, transaction);
NewFiles.Remove(fileName); NewFiles.Remove(fileName);
if (transaction.StartSend()) if (transaction.StartSend())
{ {
Transfers.Remove(xferID); Transfers.Remove(xferID);
} }
} }
} }
} }
} }
public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet)
{ {
if (Transfers.ContainsKey(xferID)) if (Transfers.ContainsKey(xferID))
{ {
if (Transfers[xferID].AckPacket(packet)) if (Transfers[xferID].AckPacket(packet))
{ {
{ {
Transfers.Remove(xferID); Transfers.Remove(xferID);
} }
} }
} }
} }
public bool AddNewFile(string fileName, byte[] data) public bool AddNewFile(string fileName, byte[] data)
{ {
lock (NewFiles) lock (NewFiles)
{ {
if (NewFiles.ContainsKey(fileName)) if (NewFiles.ContainsKey(fileName))
{ {
NewFiles[fileName] = data; NewFiles[fileName] = data;
} }
else else
{ {
NewFiles.Add(fileName, data); NewFiles.Add(fileName, data);
} }
} }
return true; return true;
} }
public class XferDownLoad public class XferDownLoad
{ {
public byte[] Data = new byte[0]; public byte[] Data = new byte[0];
public string FileName = String.Empty; public string FileName = String.Empty;
public ulong XferID = 0; public ulong XferID = 0;
public int DataPointer = 0; public int DataPointer = 0;
public uint Packet = 0; public uint Packet = 0;
public IClientAPI Client; public IClientAPI Client;
public uint Serial = 1; public uint Serial = 1;
private bool complete; private bool complete;
public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
{ {
FileName = fileName; FileName = fileName;
Data = data; Data = data;
XferID = xferID; XferID = xferID;
Client = client; Client = client;
} }
public XferDownLoad() public XferDownLoad()
{ {
} }
/// <summary> /// <summary>
/// Start a transfer /// Start a transfer
/// </summary> /// </summary>
/// <returns>True if the transfer is complete, false if not</returns> /// <returns>True if the transfer is complete, false if not</returns>
public bool StartSend() public bool StartSend()
{ {
if (Data.Length < 1000) if (Data.Length < 1000)
{ {
// for now (testing ) we only support files under 1000 bytes // for now (testing ) we only support files under 1000 bytes
byte[] transferData = new byte[Data.Length + 4]; byte[] transferData = new byte[Data.Length + 4];
Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
Array.Copy(Data, 0, transferData, 4, Data.Length); Array.Copy(Data, 0, transferData, 4, Data.Length);
Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); Client.SendXferPacket(XferID, 0 + 0x80000000, transferData);
complete = true; complete = true;
} }
else else
{ {
byte[] transferData = new byte[1000 + 4]; byte[] transferData = new byte[1000 + 4];
Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
Array.Copy(Data, 0, transferData, 4, 1000); Array.Copy(Data, 0, transferData, 4, 1000);
Client.SendXferPacket(XferID, 0, transferData); Client.SendXferPacket(XferID, 0, transferData);
Packet++; Packet++;
DataPointer = 1000; DataPointer = 1000;
} }
return complete; return complete;
} }
/// <summary> /// <summary>
/// Respond to an ack packet from the client /// Respond to an ack packet from the client
/// </summary> /// </summary>
/// <param name="packet"></param> /// <param name="packet"></param>
/// <returns>True if the transfer is complete, false otherwise</returns> /// <returns>True if the transfer is complete, false otherwise</returns>
public bool AckPacket(uint packet) public bool AckPacket(uint packet)
{ {
if (!complete) if (!complete)
{ {
if ((Data.Length - DataPointer) > 1000) if ((Data.Length - DataPointer) > 1000)
{ {
byte[] transferData = new byte[1000]; byte[] transferData = new byte[1000];
Array.Copy(Data, DataPointer, transferData, 0, 1000); Array.Copy(Data, DataPointer, transferData, 0, 1000);
Client.SendXferPacket(XferID, Packet, transferData); Client.SendXferPacket(XferID, Packet, transferData);
Packet++; Packet++;
DataPointer += 1000; DataPointer += 1000;
} }
else else
{ {
byte[] transferData = new byte[Data.Length - DataPointer]; byte[] transferData = new byte[Data.Length - DataPointer];
Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer);
uint endPacket = Packet |= (uint) 0x80000000; uint endPacket = Packet |= (uint) 0x80000000;
Client.SendXferPacket(XferID, endPacket, transferData); Client.SendXferPacket(XferID, endPacket, transferData);
Packet++; Packet++;
DataPointer += (Data.Length - DataPointer); DataPointer += (Data.Length - DataPointer);
complete = true; complete = true;
} }
} }
return complete; return complete;
} }
} }
} }
} }

View File

@ -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<AvatarAppearance>
{
public AppearanceRowMapper(BaseSchema schema, AvatarAppearance obj)
: base(schema, obj)
{
}
}
public class AppearanceTableMapper : BaseTableMapper<AppearanceRowMapper, Guid>
{
public AppearanceTableMapper(BaseDatabaseConnector database, string tableName)
: base(database, tableName)
{
BaseSchema<AppearanceRowMapper> rowMapperSchema = new BaseSchema<AppearanceRowMapper>(this);
m_schema = rowMapperSchema;
m_keyFieldMapper = rowMapperSchema.AddMapping<Guid>("UUID",
delegate(AppearanceRowMapper mapper) { return mapper.Object.ScenePresenceID.UUID; },
delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.ScenePresenceID = new libsecondlife.LLUUID(value.ToString()); });
rowMapperSchema.AddMapping<uint>("Serial",
delegate(AppearanceRowMapper mapper) { return (uint)mapper.Object.WearablesSerial; },
delegate(AppearanceRowMapper mapper, uint value) { mapper.Object.WearablesSerial = (int)value; });
rowMapperSchema.AddMapping<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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<Guid>("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;
}
}
}
}*/

View File

@ -1,338 +1,338 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* /*
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using libsecondlife; using libsecondlife;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Communications.Cache;
using OpenSim.Data.MySQLMapper; using OpenSim.Data.MySQLMapper;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using OpenSim.Data.Base; using OpenSim.Data.Base;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules
{ {
public class AvatarFactoryModule : IAvatarFactory public class AvatarFactoryModule : IAvatarFactory
{ {
private Scene m_scene = null; private Scene m_scene = null;
private readonly Dictionary<LLUUID, AvatarAppearance> m_avatarsAppearance = new Dictionary<LLUUID, AvatarAppearance>(); private readonly Dictionary<LLUUID, AvatarAppearance> m_avatarsAppearance = new Dictionary<LLUUID, AvatarAppearance>();
private bool m_enablePersist = false; private bool m_enablePersist = false;
private string m_connectionString; private string m_connectionString;
private bool m_configured = false; private bool m_configured = false;
private BaseDatabaseConnector m_databaseMapper; private BaseDatabaseConnector m_databaseMapper;
private AppearanceTableMapper m_appearanceMapper; private AppearanceTableMapper m_appearanceMapper;
private Dictionary<LLUUID, EventWaitHandle> m_fetchesInProgress = new Dictionary<LLUUID, EventWaitHandle>(); private Dictionary<LLUUID, EventWaitHandle> m_fetchesInProgress = new Dictionary<LLUUID, EventWaitHandle>();
private object m_syncLock = new object(); private object m_syncLock = new object();
public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance) public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
{ {
//should only let one thread at a time do this part //should only let one thread at a time do this part
EventWaitHandle waitHandle = null; EventWaitHandle waitHandle = null;
bool fetchInProgress = false; bool fetchInProgress = false;
lock (m_syncLock) lock (m_syncLock)
{ {
appearance = CheckCache(avatarId); appearance = CheckCache(avatarId);
if (appearance != null) if (appearance != null)
{ {
return true; return true;
} }
//not in cache so check to see if another thread is already fetching it //not in cache so check to see if another thread is already fetching it
if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle)) if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle))
{ {
fetchInProgress = true; fetchInProgress = true;
} }
else else
{ {
fetchInProgress = false; fetchInProgress = false;
//no thread already fetching this appearance, so add a wait handle to list //no thread already fetching this appearance, so add a wait handle to list
//for any following threads that want the same appearance //for any following threads that want the same appearance
waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
m_fetchesInProgress.Add(avatarId, waitHandle); m_fetchesInProgress.Add(avatarId, waitHandle);
} }
} }
if (fetchInProgress) if (fetchInProgress)
{ {
waitHandle.WaitOne(); waitHandle.WaitOne();
appearance = CheckCache(avatarId); appearance = CheckCache(avatarId);
if (appearance != null) if (appearance != null)
{ {
waitHandle = null; waitHandle = null;
return true; return true;
} }
else else
{ {
waitHandle = null; waitHandle = null;
return false; return false;
} }
} }
else else
{ {
Thread.Sleep(5000); Thread.Sleep(5000);
//this is the first thread to request this appearance //this is the first thread to request this appearance
//so let it check the db and if not found then create a default appearance //so let it check the db and if not found then create a default appearance
//and add that to the cache //and add that to the cache
appearance = CheckDatabase(avatarId); appearance = CheckDatabase(avatarId);
if (appearance != null) if (appearance != null)
{ {
//appearance has now been added to cache so lets pulse any waiting threads //appearance has now been added to cache so lets pulse any waiting threads
lock (m_syncLock) lock (m_syncLock)
{ {
m_fetchesInProgress.Remove(avatarId); m_fetchesInProgress.Remove(avatarId);
waitHandle.Set(); waitHandle.Set();
} }
// waitHandle.Close(); // waitHandle.Close();
waitHandle = null; waitHandle = null;
return true; return true;
} }
//not found a appearance for the user, so create a new default one //not found a appearance for the user, so create a new default one
appearance = CreateDefault(avatarId); appearance = CreateDefault(avatarId);
if (appearance != null) if (appearance != null)
{ {
//update database //update database
if (m_enablePersist) if (m_enablePersist)
{ {
m_appearanceMapper.Add(avatarId.UUID, appearance); m_appearanceMapper.Add(avatarId.UUID, appearance);
} }
//add appearance to dictionary cache //add appearance to dictionary cache
lock (m_avatarsAppearance) lock (m_avatarsAppearance)
{ {
m_avatarsAppearance[avatarId] = appearance; m_avatarsAppearance[avatarId] = appearance;
} }
//appearance has now been added to cache so lets pulse any waiting threads //appearance has now been added to cache so lets pulse any waiting threads
lock (m_syncLock) lock (m_syncLock)
{ {
m_fetchesInProgress.Remove(avatarId); m_fetchesInProgress.Remove(avatarId);
waitHandle.Set(); waitHandle.Set();
} }
// waitHandle.Close(); // waitHandle.Close();
waitHandle = null; waitHandle = null;
return true; return true;
} }
else else
{ {
//something went wrong, so release the wait handle and remove it //something went wrong, so release the wait handle and remove it
//all waiting threads will fail to find cached appearance //all waiting threads will fail to find cached appearance
//but its better for them to fail than wait for ever //but its better for them to fail than wait for ever
lock (m_syncLock) lock (m_syncLock)
{ {
m_fetchesInProgress.Remove(avatarId); m_fetchesInProgress.Remove(avatarId);
waitHandle.Set(); waitHandle.Set();
} }
//waitHandle.Close(); //waitHandle.Close();
waitHandle = null; waitHandle = null;
return false; return false;
} }
} }
} }
private AvatarAppearance CreateDefault(LLUUID avatarId) private AvatarAppearance CreateDefault(LLUUID avatarId)
{ {
AvatarAppearance appearance = null; AvatarAppearance appearance = null;
AvatarWearable[] wearables; AvatarWearable[] wearables;
byte[] visualParams; byte[] visualParams;
GetDefaultAvatarAppearance(out wearables, out visualParams); GetDefaultAvatarAppearance(out wearables, out visualParams);
appearance = new AvatarAppearance(avatarId, wearables, visualParams); appearance = new AvatarAppearance(avatarId, wearables, visualParams);
return appearance; return appearance;
} }
private AvatarAppearance CheckDatabase(LLUUID avatarId) private AvatarAppearance CheckDatabase(LLUUID avatarId)
{ {
AvatarAppearance appearance = null; AvatarAppearance appearance = null;
if (m_enablePersist) if (m_enablePersist)
{ {
if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance)) if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance))
{ {
appearance.VisualParams = GetDefaultVisualParams(); appearance.VisualParams = GetDefaultVisualParams();
appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry(); appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry();
lock (m_avatarsAppearance) lock (m_avatarsAppearance)
{ {
m_avatarsAppearance[avatarId] = appearance; m_avatarsAppearance[avatarId] = appearance;
} }
} }
} }
return appearance; return appearance;
} }
private AvatarAppearance CheckCache(LLUUID avatarId) private AvatarAppearance CheckCache(LLUUID avatarId)
{ {
AvatarAppearance appearance = null; AvatarAppearance appearance = null;
lock (m_avatarsAppearance) lock (m_avatarsAppearance)
{ {
if (m_avatarsAppearance.ContainsKey(avatarId)) if (m_avatarsAppearance.ContainsKey(avatarId))
{ {
appearance = m_avatarsAppearance[avatarId]; appearance = m_avatarsAppearance[avatarId];
} }
} }
return appearance; return appearance;
} }
public void Initialise(Scene scene, IConfigSource source) public void Initialise(Scene scene, IConfigSource source)
{ {
scene.RegisterModuleInterface<IAvatarFactory>(this); scene.RegisterModuleInterface<IAvatarFactory>(this);
scene.EventManager.OnNewClient += NewClient; scene.EventManager.OnNewClient += NewClient;
if (m_scene == null) if (m_scene == null)
{ {
m_scene = scene; m_scene = scene;
} }
if (!m_configured) if (!m_configured)
{ {
m_configured = true; m_configured = true;
try try
{ {
m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false); m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false);
m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", ""); m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", "");
} }
catch (Exception) catch (Exception)
{ {
} }
if (m_enablePersist) if (m_enablePersist)
{ {
m_databaseMapper = new MySQLDatabaseMapper(m_connectionString); m_databaseMapper = new MySQLDatabaseMapper(m_connectionString);
m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance"); m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance");
} }
} }
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "Default Avatar Factory"; } get { return "Default Avatar Factory"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return true; } get { return true; }
} }
public void NewClient(IClientAPI client) public void NewClient(IClientAPI client)
{ {
client.OnAvatarNowWearing += AvatarIsWearing; client.OnAvatarNowWearing += AvatarIsWearing;
} }
public void RemoveClient(IClientAPI client) public void RemoveClient(IClientAPI client)
{ {
// client.OnAvatarNowWearing -= AvatarIsWearing; // client.OnAvatarNowWearing -= AvatarIsWearing;
} }
public void AvatarIsWearing(Object sender, AvatarWearingArgs e) public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
{ {
IClientAPI clientView = (IClientAPI)sender; IClientAPI clientView = (IClientAPI)sender;
CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId); CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
if (profile != null) if (profile != null)
{ {
if (profile.RootFolder != null) if (profile.RootFolder != null)
{ {
if (m_avatarsAppearance.ContainsKey(clientView.AgentId)) if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
{ {
AvatarAppearance avatAppearance = null; AvatarAppearance avatAppearance = null;
lock (m_avatarsAppearance) lock (m_avatarsAppearance)
{ {
avatAppearance = m_avatarsAppearance[clientView.AgentId]; avatAppearance = m_avatarsAppearance[clientView.AgentId];
} }
foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
{ {
if (wear.Type < 13) if (wear.Type < 13)
{ {
if (wear.ItemID == LLUUID.Zero) if (wear.ItemID == LLUUID.Zero)
{ {
avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero; avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero;
avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero; avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero;
UpdateDatabase(clientView.AgentId, avatAppearance); UpdateDatabase(clientView.AgentId, avatAppearance);
} }
else else
{ {
LLUUID assetId; LLUUID assetId;
InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID); InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID);
if (baseItem != null) if (baseItem != null)
{ {
assetId = baseItem.assetID; assetId = baseItem.assetID;
avatAppearance.Wearables[wear.Type].AssetID = assetId; avatAppearance.Wearables[wear.Type].AssetID = assetId;
avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
UpdateDatabase(clientView.AgentId, avatAppearance); UpdateDatabase(clientView.AgentId, avatAppearance);
} }
} }
} }
} }
} }
} }
} }
} }
public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance) public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance)
{ {
if (m_enablePersist) if (m_enablePersist)
{ {
m_appearanceMapper.Update(userID.UUID, avatAppearance); m_appearanceMapper.Update(userID.UUID, avatAppearance);
} }
} }
public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
{ {
visualParams = GetDefaultVisualParams(); visualParams = GetDefaultVisualParams();
wearables = AvatarWearable.DefaultWearables; wearables = AvatarWearable.DefaultWearables;
} }
private static byte[] GetDefaultVisualParams() private static byte[] GetDefaultVisualParams()
{ {
byte[] visualParams; byte[] visualParams;
visualParams = new byte[218]; visualParams = new byte[218];
for (int i = 0; i < 218; i++) for (int i = 0; i < 218; i++)
{ {
visualParams[i] = 100; visualParams[i] = 100;
} }
return visualParams; return visualParams;
} }
} }
}*/ }*/

View File

@ -1,278 +1,278 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using libsecondlife; using libsecondlife;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Avatar.Groups
{ {
public class GroupsModule : IRegionModule public class GroupsModule : IRegionModule
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<Scene> m_scene = new List<Scene>(); private List<Scene> m_scene = new List<Scene>();
private Dictionary<LLUUID, IClientAPI> m_iclientmap = new Dictionary<LLUUID, IClientAPI>(); private Dictionary<LLUUID, IClientAPI> m_iclientmap = new Dictionary<LLUUID, IClientAPI>();
private Dictionary<LLUUID, GroupData> m_groupmap = new Dictionary<LLUUID, GroupData>(); private Dictionary<LLUUID, GroupData> m_groupmap = new Dictionary<LLUUID, GroupData>();
private Dictionary<LLUUID, GroupList> m_grouplistmap = new Dictionary<LLUUID, GroupList>(); private Dictionary<LLUUID, GroupList> m_grouplistmap = new Dictionary<LLUUID, GroupList>();
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
lock (m_scene) lock (m_scene)
{ {
m_scene.Add(scene); m_scene.Add(scene);
} }
scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnNewClient += OnNewClient;
scene.EventManager.OnClientClosed += OnClientClosed; scene.EventManager.OnClientClosed += OnClientClosed;
scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage; scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage;
//scene.EventManager. //scene.EventManager.
} }
private void OnNewClient(IClientAPI client) private void OnNewClient(IClientAPI client)
{ {
// All friends establishment protocol goes over instant message // All friends establishment protocol goes over instant message
// There's no way to send a message from the sim // There's no way to send a message from the sim
// to a user to 'add a friend' without causing dialog box spam // 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 // 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 // Generated by LoginService. The friends are retreived from the database by the UserManager
// Subscribe to instant messages // Subscribe to instant messages
client.OnInstantMessage += OnInstantMessage; client.OnInstantMessage += OnInstantMessage;
client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
lock (m_iclientmap) lock (m_iclientmap)
{ {
if (!m_iclientmap.ContainsKey(client.AgentId)) if (!m_iclientmap.ContainsKey(client.AgentId))
{ {
m_iclientmap.Add(client.AgentId, client); m_iclientmap.Add(client.AgentId, client);
} }
} }
GroupData OpenSimulatorGroup = new GroupData(); GroupData OpenSimulatorGroup = new GroupData();
OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester"; OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester";
OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120"); OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120");
OpenSimulatorGroup.GroupMembers.Add(client.AgentId); OpenSimulatorGroup.GroupMembers.Add(client.AgentId);
OpenSimulatorGroup.groupName = "OpenSimulator Testing"; OpenSimulatorGroup.groupName = "OpenSimulator Testing";
OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome; OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome;
OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester"); OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester");
lock (m_groupmap) lock (m_groupmap)
{ {
if (!m_groupmap.ContainsKey(client.AgentId)) if (!m_groupmap.ContainsKey(client.AgentId))
{ {
m_groupmap.Add(client.AgentId, OpenSimulatorGroup); m_groupmap.Add(client.AgentId, OpenSimulatorGroup);
} }
} }
GroupList testGroupList = new GroupList(); GroupList testGroupList = new GroupList();
testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120")); testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120"));
lock (m_grouplistmap) lock (m_grouplistmap)
{ {
if (!m_grouplistmap.ContainsKey(client.AgentId)) if (!m_grouplistmap.ContainsKey(client.AgentId))
{ {
m_grouplistmap.Add(client.AgentId, testGroupList); m_grouplistmap.Add(client.AgentId, testGroupList);
} }
} }
m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group"); m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group");
} }
private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID) private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID)
{ {
string firstname = remoteClient.FirstName; string firstname = remoteClient.FirstName;
string lastname = remoteClient.LastName; string lastname = remoteClient.LastName;
LLUUID ActiveGroupID = LLUUID.Zero; LLUUID ActiveGroupID = LLUUID.Zero;
uint ActiveGroupPowers = 0; uint ActiveGroupPowers = 0;
string ActiveGroupName = ""; string ActiveGroupName = "";
string ActiveGroupTitle = ""; string ActiveGroupTitle = "";
bool foundUser = false; bool foundUser = false;
lock (m_iclientmap) lock (m_iclientmap)
{ {
if (m_iclientmap.ContainsKey(remoteClient.AgentId)) if (m_iclientmap.ContainsKey(remoteClient.AgentId))
{ {
foundUser = true; foundUser = true;
} }
} }
if (foundUser) if (foundUser)
{ {
lock (m_groupmap) lock (m_groupmap)
{ {
if (m_groupmap.ContainsKey(remoteClient.AgentId)) if (m_groupmap.ContainsKey(remoteClient.AgentId))
{ {
GroupData grp = m_groupmap[remoteClient.AgentId]; GroupData grp = m_groupmap[remoteClient.AgentId];
if (grp != null) if (grp != null)
{ {
ActiveGroupID = grp.GroupID; ActiveGroupID = grp.GroupID;
ActiveGroupName = grp.groupName; ActiveGroupName = grp.groupName;
ActiveGroupPowers = grp.groupPowers; ActiveGroupPowers = grp.groupPowers;
ActiveGroupTitle = grp.ActiveGroupTitle; ActiveGroupTitle = grp.ActiveGroupTitle;
} }
//remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle); //remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle);
} }
} }
} }
} }
private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID, private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
LLUUID fromAgentSession, LLUUID toAgentID, LLUUID fromAgentSession, LLUUID toAgentID,
LLUUID imSessionID, uint timestamp, string fromAgentName, LLUUID imSessionID, uint timestamp, string fromAgentName,
string message, byte dialog, bool fromGroup, byte offline, string message, byte dialog, bool fromGroup, byte offline,
uint ParentEstateID, LLVector3 Position, LLUUID RegionID, uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
byte[] binaryBucket) byte[] binaryBucket)
{ {
} }
private void OnGridInstantMessage(GridInstantMessage msg) private void OnGridInstantMessage(GridInstantMessage msg)
{ {
// Trigger the above event handler // Trigger the above event handler
OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, 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), new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
msg.binaryBucket); msg.binaryBucket);
} }
private void OnClientClosed(LLUUID agentID) private void OnClientClosed(LLUUID agentID)
{ {
lock (m_iclientmap) lock (m_iclientmap)
{ {
if (m_iclientmap.ContainsKey(agentID)) if (m_iclientmap.ContainsKey(agentID))
{ {
IClientAPI cli = m_iclientmap[agentID]; IClientAPI cli = m_iclientmap[agentID];
if (cli != null) if (cli != null)
{ {
m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName); m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName);
} }
else else
{ {
m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString()); m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString());
} }
m_iclientmap.Remove(agentID); m_iclientmap.Remove(agentID);
} }
} }
lock (m_groupmap) lock (m_groupmap)
{ {
if (m_groupmap.ContainsKey(agentID)) if (m_groupmap.ContainsKey(agentID))
{ {
m_groupmap.Remove(agentID); m_groupmap.Remove(agentID);
} }
} }
lock (m_grouplistmap) lock (m_grouplistmap)
{ {
if (m_grouplistmap.ContainsKey(agentID)) if (m_grouplistmap.ContainsKey(agentID))
{ {
m_grouplistmap.Remove(agentID); m_grouplistmap.Remove(agentID);
} }
} }
GC.Collect(); GC.Collect();
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
m_log.Info("[GROUP]: Shutting down group module."); m_log.Info("[GROUP]: Shutting down group module.");
lock (m_iclientmap) lock (m_iclientmap)
{ {
m_iclientmap.Clear(); m_iclientmap.Clear();
} }
lock (m_groupmap) lock (m_groupmap)
{ {
m_groupmap.Clear(); m_groupmap.Clear();
} }
lock (m_grouplistmap) lock (m_grouplistmap)
{ {
m_grouplistmap.Clear(); m_grouplistmap.Clear();
} }
GC.Collect(); GC.Collect();
} }
public string Name public string Name
{ {
get { return "GroupsModule"; } get { return "GroupsModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return true; } get { return true; }
} }
} }
public class GroupData public class GroupData
{ {
public LLUUID GroupID; public LLUUID GroupID;
public string groupName; public string groupName;
public string ActiveGroupTitle; public string ActiveGroupTitle;
public List<string> GroupTitles; public List<string> GroupTitles;
public List<LLUUID> GroupMembers; public List<LLUUID> GroupMembers;
public uint groupPowers = (uint)(GroupPowers.LandAllowLandmark | GroupPowers.LandAllowSetHome); public uint groupPowers = (uint)(GroupPowers.LandAllowLandmark | GroupPowers.LandAllowSetHome);
public GroupPowers ActiveGroupPowers public GroupPowers ActiveGroupPowers
{ {
set set
{ {
groupPowers = (uint) value; groupPowers = (uint) value;
} }
get get
{ {
return (GroupPowers)groupPowers; return (GroupPowers)groupPowers;
} }
} }
public GroupData() public GroupData()
{ {
GroupTitles = new List<string>(); GroupTitles = new List<string>();
GroupMembers = new List<LLUUID>(); GroupMembers = new List<LLUUID>();
} }
} }
public class GroupList public class GroupList
{ {
public List<LLUUID> m_GroupList; public List<LLUUID> m_GroupList;
public GroupList() public GroupList()
{ {
m_GroupList = new List<LLUUID>(); m_GroupList = new List<LLUUID>();
} }
} }
} }

View File

@ -1,159 +1,157 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.Collections; using System.Collections.Generic;
using System.Collections.Generic; using libsecondlife;
using libsecondlife; using Nini.Config;
using Nini.Config; using OpenSim.Framework;
using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
namespace OpenSim.Region.Environment.Modules {
{ public class InstantMessageModule : IRegionModule
public class InstantMessageModule : IRegionModule {
{ private readonly List<Scene> m_scenes = new List<Scene>();
private List<Scene> m_scenes = new List<Scene>();
private Hashtable m_RegionInfoCache = new Hashtable(); public void Initialise(Scene scene, IConfigSource config)
{
public void Initialise(Scene scene, IConfigSource config) lock (m_scenes)
{ {
lock (m_scenes) if (m_scenes.Count == 0)
{ {
if (m_scenes.Count == 0) //scene.AddXmlRPCHandler("avatar_location_update", processPresenceUpdate);
{ }
//scene.AddXmlRPCHandler("avatar_location_update", processPresenceUpdate);
} if (!m_scenes.Contains(scene))
{
if (!m_scenes.Contains(scene)) m_scenes.Add(scene);
{ scene.EventManager.OnNewClient += OnNewClient;
m_scenes.Add(scene); scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage;
scene.EventManager.OnNewClient += OnNewClient; }
scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage; }
} }
}
} private void OnNewClient(IClientAPI client)
{
private void OnNewClient(IClientAPI client) client.OnInstantMessage += OnInstantMessage;
{ }
client.OnInstantMessage += OnInstantMessage;
} private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID,
LLUUID fromAgentSession, LLUUID toAgentID,
private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID, LLUUID imSessionID, uint timestamp, string fromAgentName,
LLUUID fromAgentSession, LLUUID toAgentID, string message, byte dialog, bool fromGroup, byte offline,
LLUUID imSessionID, uint timestamp, string fromAgentName, uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
string message, byte dialog, bool fromGroup, byte offline, byte[] binaryBucket)
uint ParentEstateID, LLVector3 Position, LLUUID RegionID, {
byte[] binaryBucket) bool dialogHandledElsewhere
{ = ((dialog == 38) || (dialog == 39) || (dialog == 40)
bool dialogHandledElsewhere || dialog == (byte)InstantMessageDialog.InventoryOffered
= ((dialog == (byte)38) || (dialog == (byte)39) || (dialog == (byte)40) || dialog == (byte)InstantMessageDialog.InventoryAccepted
|| dialog == (byte)InstantMessageDialog.InventoryOffered || dialog == (byte)InstantMessageDialog.InventoryDeclined);
|| 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.
// 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))
// 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)
// Try root avatar only first {
foreach (Scene scene in m_scenes) if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
{ {
if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) // Local message
{ ScenePresence user = (ScenePresence)scene.Entities[toAgentID];
// Local message if (!user.IsChildAgent)
ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; {
if (!user.IsChildAgent) user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
{ toAgentID, imSessionID, fromAgentName, dialog,
user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, timestamp);
toAgentID, imSessionID, fromAgentName, dialog, // Message sent
timestamp); return;
// Message sent }
return; }
} }
}
} // try child avatar second
foreach (Scene scene in m_scenes)
// try child avatar second {
foreach (Scene scene in m_scenes) if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
{ {
if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) // Local message
{ ScenePresence user = (ScenePresence)scene.Entities[toAgentID];
// Local message
ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
toAgentID, imSessionID, fromAgentName, dialog,
user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, timestamp);
toAgentID, imSessionID, fromAgentName, dialog, // Message sent
timestamp); return;
// Message sent
return; }
}
}
} }
}
// Still here, try send via Grid
// TODO
// 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.
// 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)
{
private void OnGridInstantMessage(GridInstantMessage msg) // Trigger the above event handler
{ OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
// Trigger the above event handler new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, new LLVector3(msg.Position.x,msg.Position.y,msg.Position.z), new LLUUID(msg.RegionID),
msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, msg.binaryBucket);
new LLVector3(msg.Position.x,msg.Position.y,msg.Position.z), new LLUUID(msg.RegionID),
msg.binaryBucket); }
} public void PostInitialise()
{
public void PostInitialise() }
{
} public void Close()
{
public void Close() }
{
} public string Name
{
public string Name get { return "InstantMessageModule"; }
{ }
get { return "InstantMessageModule"; }
} public bool IsSharedModule
{
public bool IsSharedModule get { return true; }
{ }
get { return true; } }
} }
}
}

View File

@ -1,216 +1,216 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using libsecondlife; using libsecondlife;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Avatar.Inventory
{ {
public class InventoryModule : IRegionModule public class InventoryModule : IRegionModule
{ {
private static readonly ILog m_log private static readonly ILog m_log
= LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
/// <summary> /// <summary>
/// We need to keep track of the pending item offers between clients since the itemId offered only /// 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 /// occurs in the initial offer message, not the accept message. So this dictionary links
/// IM Session Ids to ItemIds /// IM Session Ids to ItemIds
/// </summary> /// </summary>
private IDictionary<LLUUID, LLUUID> m_pendingOffers = new Dictionary<LLUUID, LLUUID>(); private IDictionary<LLUUID, LLUUID> m_pendingOffers = new Dictionary<LLUUID, LLUUID>();
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
m_scene = scene; m_scene = scene;
scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnNewClient += OnNewClient;
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "InventoryModule"; } get { return "InventoryModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return false; } get { return false; }
} }
private void OnNewClient(IClientAPI client) private void OnNewClient(IClientAPI client)
{ {
// Inventory giving is conducted via instant message // Inventory giving is conducted via instant message
client.OnInstantMessage += OnInstantMessage; client.OnInstantMessage += OnInstantMessage;
} }
private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID, private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
LLUUID fromAgentSession, LLUUID toAgentID, LLUUID fromAgentSession, LLUUID toAgentID,
LLUUID imSessionID, uint timestamp, string fromAgentName, LLUUID imSessionID, uint timestamp, string fromAgentName,
string message, byte dialog, bool fromGroup, byte offline, string message, byte dialog, bool fromGroup, byte offline,
uint ParentEstateID, LLVector3 Position, LLUUID RegionID, uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
byte[] binaryBucket) byte[] binaryBucket)
{ {
if (dialog == (byte)InstantMessageDialog.InventoryOffered) if (dialog == (byte)InstantMessageDialog.InventoryOffered)
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}", "[AGENT INVENTORY]: Routing inventory offering message from {0}, {1} to {2}",
client.AgentId, client.Name, toAgentID); client.AgentId, client.Name, toAgentID);
if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
{ {
ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID];
if (!user.IsChildAgent) if (!user.IsChildAgent)
{ {
//byte[] rawId = new byte[16]; //byte[] rawId = new byte[16];
// First byte of the array is probably the item type // First byte of the array is probably the item type
// Next 16 bytes are the UUID // Next 16 bytes are the UUID
//Array.Copy(binaryBucket, 1, rawId, 0, 16); //Array.Copy(binaryBucket, 1, rawId, 0, 16);
//LLUUID itemId = new LLUUID(new Guid(rawId)); //LLUUID itemId = new LLUUID(new Guid(rawId));
LLUUID itemId = new LLUUID(binaryBucket, 1); LLUUID itemId = new LLUUID(binaryBucket, 1);
m_log.DebugFormat( m_log.DebugFormat(
"[AGENT INVENTORY]: ItemId for giving is {0}", itemId); "[AGENT INVENTORY]: ItemId for giving is {0}", itemId);
m_pendingOffers[imSessionID] = itemId; m_pendingOffers[imSessionID] = itemId;
user.ControllingClient.SendInstantMessage( user.ControllingClient.SendInstantMessage(
fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
dialog, timestamp, binaryBucket); dialog, timestamp, binaryBucket);
return; return;
} }
else else
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
toAgentID, client.AgentId, client.Name, message); toAgentID, client.AgentId, client.Name, message);
} }
} }
else else
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
toAgentID, client.AgentId, client.Name, message); toAgentID, client.AgentId, client.Name, message);
} }
} }
else if (dialog == (byte)InstantMessageDialog.InventoryAccepted) else if (dialog == (byte)InstantMessageDialog.InventoryAccepted)
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}", "[AGENT INVENTORY]: Routing inventory accepted message from {0}, {1} to {2}",
client.AgentId, client.Name, toAgentID); client.AgentId, client.Name, toAgentID);
if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
{ {
ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID];
if (!user.IsChildAgent) if (!user.IsChildAgent)
{ {
user.ControllingClient.SendInstantMessage( user.ControllingClient.SendInstantMessage(
fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
dialog, timestamp, binaryBucket); dialog, timestamp, binaryBucket);
if (m_pendingOffers.ContainsKey(imSessionID)) if (m_pendingOffers.ContainsKey(imSessionID))
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]); "[AGENT INVENTORY]: Accepted item id {0}", m_pendingOffers[imSessionID]);
// Since the message originates from the accepting client, the toAgentID is // Since the message originates from the accepting client, the toAgentID is
// the agent giving the item. // the agent giving the item.
m_scene.GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]); m_scene.GiveInventoryItem(client, toAgentID, m_pendingOffers[imSessionID]);
m_pendingOffers.Remove(imSessionID); m_pendingOffers.Remove(imSessionID);
} }
else else
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
"[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept", "[AGENT INVENTORY]: Could not find an item associated with session id {0} to accept",
imSessionID); imSessionID);
} }
return; return;
} }
else else
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!", "[AGENT INVENTORY]: Agent {0} targeted for inventory give by {1}, {2} of {3} was a child agent!",
toAgentID, client.AgentId, client.Name, message); toAgentID, client.AgentId, client.Name, message);
} }
} }
else else
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}", "[AGENT INVENTORY]: Could not find agent {0} for user {1}, {2} to give {3}",
toAgentID, client.AgentId, client.Name, message); toAgentID, client.AgentId, client.Name, message);
} }
} }
else if (dialog == (byte)InstantMessageDialog.InventoryDeclined) else if (dialog == (byte)InstantMessageDialog.InventoryDeclined)
{ {
if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence) if (m_scene.Entities.ContainsKey(toAgentID) && m_scene.Entities[toAgentID] is ScenePresence)
{ {
ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID];
if (!user.IsChildAgent) if (!user.IsChildAgent)
{ {
user.ControllingClient.SendInstantMessage( user.ControllingClient.SendInstantMessage(
fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName, fromAgentID, fromAgentSession, message, toAgentID, imSessionID, fromAgentName,
dialog, timestamp, binaryBucket); dialog, timestamp, binaryBucket);
if (m_pendingOffers.ContainsKey(imSessionID)) if (m_pendingOffers.ContainsKey(imSessionID))
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]); "[AGENT INVENTORY]: Declined item id {0}", m_pendingOffers[imSessionID]);
m_pendingOffers.Remove(imSessionID); m_pendingOffers.Remove(imSessionID);
} }
else else
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
"[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline", "[AGENT INVENTORY]: Could not find an item associated with session id {0} to decline",
imSessionID); imSessionID);
} }
} }
} }
} }
} }
} }
} }

View File

@ -1,129 +1,129 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Reflection; using System.Reflection;
using libsecondlife; using libsecondlife;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Avatar.Profiles
{ {
public class AvatarProfilesModule : IRegionModule public class AvatarProfilesModule : IRegionModule
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
public AvatarProfilesModule() public AvatarProfilesModule()
{ {
} }
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
m_scene = scene; m_scene = scene;
m_scene.EventManager.OnNewClient += NewClient; m_scene.EventManager.OnNewClient += NewClient;
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "AvatarProfilesModule"; } get { return "AvatarProfilesModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return false; } get { return false; }
} }
public void NewClient(IClientAPI client) public void NewClient(IClientAPI client)
{ {
client.OnRequestAvatarProperties += RequestAvatarProperty; client.OnRequestAvatarProperties += RequestAvatarProperty;
client.OnUpdateAvatarProperties += UpdateAvatarProperties; client.OnUpdateAvatarProperties += UpdateAvatarProperties;
} }
public void RemoveClient(IClientAPI client) public void RemoveClient(IClientAPI client)
{ {
client.OnRequestAvatarProperties -= RequestAvatarProperty; client.OnRequestAvatarProperties -= RequestAvatarProperty;
client.OnUpdateAvatarProperties -= UpdateAvatarProperties; client.OnUpdateAvatarProperties -= UpdateAvatarProperties;
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="avatarID"></param> /// <param name="avatarID"></param>
public void RequestAvatarProperty(IClientAPI remoteClient, LLUUID avatarID) public void RequestAvatarProperty(IClientAPI remoteClient, LLUUID avatarID)
{ {
// FIXME: finish adding fields such as url, masking, etc. // FIXME: finish adding fields such as url, masking, etc.
LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000"); LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000");
UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID); UserProfileData profile = m_scene.CommsManager.UserService.GetUserProfile(avatarID);
if (null != profile) if (null != profile)
{ {
remoteClient.SendAvatarProperties(profile.ID, profile.AboutText, remoteClient.SendAvatarProperties(profile.ID, profile.AboutText,
Util.ToDateTime(profile.Created).ToString(), Util.ToDateTime(profile.Created).ToString(),
String.Empty, profile.FirstLifeAboutText, profile.CanDoMask, String.Empty, profile.FirstLifeAboutText, profile.CanDoMask,
profile.FirstLifeImage, profile.Image, String.Empty, partner); profile.FirstLifeImage, profile.Image, String.Empty, partner);
} }
else else
{ {
m_log.Debug("[AvatarProfilesModule]: Got null for profile for " + avatarID.ToString()); m_log.Debug("[AvatarProfilesModule]: Got null for profile for " + avatarID.ToString());
} }
} }
public void UpdateAvatarProperties(IClientAPI remoteClient, UserProfileData newProfile) public void UpdateAvatarProperties(IClientAPI remoteClient, UserProfileData newProfile)
{ {
UserProfileData Profile = m_scene.CommsManager.UserService.GetUserProfile(newProfile.ID); 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 it's the profile of the user requesting the update, then we change only a few things.
if (remoteClient.AgentId.CompareTo(Profile.ID) == 0) if (remoteClient.AgentId.CompareTo(Profile.ID) == 0)
{ {
Profile.Image = newProfile.Image; Profile.Image = newProfile.Image;
Profile.FirstLifeImage = newProfile.FirstLifeImage; Profile.FirstLifeImage = newProfile.FirstLifeImage;
Profile.AboutText = newProfile.AboutText; Profile.AboutText = newProfile.AboutText;
Profile.FirstLifeAboutText = newProfile.FirstLifeAboutText; Profile.FirstLifeAboutText = newProfile.FirstLifeAboutText;
} }
else else
{ {
return; return;
} }
if (m_scene.CommsManager.UserService.UpdateUserProfileProperties(Profile)) if (m_scene.CommsManager.UserService.UpdateUserProfileProperties(Profile))
{ {
RequestAvatarProperty(remoteClient, newProfile.ID); RequestAvatarProperty(remoteClient, newProfile.ID);
} }
} }
} }
} }

View File

@ -1,285 +1,285 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections; using System.Collections;
using System.Reflection; using System.Reflection;
using libsecondlife; using libsecondlife;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using Nwc.XmlRpc; using Nwc.XmlRpc;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Servers; using OpenSim.Framework.Servers;
using OpenSim.Region.Capabilities; using OpenSim.Region.Capabilities;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using Caps=OpenSim.Region.Capabilities.Caps; using Caps=OpenSim.Region.Capabilities.Caps;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Avatar.Voice.AsterixVoice
{ {
public class AsteriskVoiceModule : IRegionModule public class AsteriskVoiceModule : IRegionModule
{ {
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
private IConfig m_config; private IConfig m_config;
private string m_asterisk; private string m_asterisk;
private string m_asterisk_password; private string m_asterisk_password;
private string m_asterisk_salt; private string m_asterisk_salt;
private int m_asterisk_timeout; private int m_asterisk_timeout;
private string m_sipDomain; private string m_sipDomain;
private string m_confDomain; private string m_confDomain;
private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
m_scene = scene; m_scene = scene;
m_config = config.Configs["AsteriskVoice"]; m_config = config.Configs["AsteriskVoice"];
if (null == m_config) if (null == m_config)
{ {
m_log.Info("[ASTERISKVOICE] no config found, plugin disabled"); m_log.Info("[ASTERISKVOICE] no config found, plugin disabled");
return; return;
} }
if (!m_config.GetBoolean("enabled", false)) if (!m_config.GetBoolean("enabled", false))
{ {
m_log.Info("[ASTERISKVOICE] plugin disabled by configuration"); m_log.Info("[ASTERISKVOICE] plugin disabled by configuration");
return; return;
} }
m_log.Info("[ASTERISKVOICE] plugin enabled"); m_log.Info("[ASTERISKVOICE] plugin enabled");
try { try {
m_sipDomain = m_config.GetString("sip_domain", String.Empty); m_sipDomain = m_config.GetString("sip_domain", String.Empty);
m_log.InfoFormat("[ASTERISKVOICE] using SIP domain {0}", m_sipDomain); m_log.InfoFormat("[ASTERISKVOICE] using SIP domain {0}", m_sipDomain);
m_confDomain = m_config.GetString("conf_domain", String.Empty); m_confDomain = m_config.GetString("conf_domain", String.Empty);
m_log.InfoFormat("[ASTERISKVOICE] using conf domain {0}", m_confDomain); m_log.InfoFormat("[ASTERISKVOICE] using conf domain {0}", m_confDomain);
m_asterisk = m_config.GetString("asterisk_frontend", String.Empty); m_asterisk = m_config.GetString("asterisk_frontend", String.Empty);
m_asterisk_password = m_config.GetString("asterisk_password", String.Empty); m_asterisk_password = m_config.GetString("asterisk_password", String.Empty);
m_asterisk_timeout = m_config.GetInt("asterisk_timeout", 3000); m_asterisk_timeout = m_config.GetInt("asterisk_timeout", 3000);
m_asterisk_salt = m_config.GetString("asterisk_salt", "Wuffwuff"); 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)) throw new Exception("missing asterisk_frontend config parameter");
if (String.IsNullOrEmpty(m_asterisk_password)) throw new Exception("missing asterisk_password 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); m_log.InfoFormat("[ASTERISKVOICE] using asterisk front end {0}", m_asterisk);
scene.EventManager.OnRegisterCaps += OnRegisterCaps; scene.EventManager.OnRegisterCaps += OnRegisterCaps;
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.Message); m_log.ErrorFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.Message);
m_log.DebugFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.ToString()); m_log.DebugFormat("[ASTERISKVOICE] plugin initialization failed: {0}", e.ToString());
return; return;
} }
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "AsteriskVoiceModule"; } get { return "AsteriskVoiceModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return false; } get { return false; }
} }
public void OnRegisterCaps(LLUUID agentID, Caps caps) public void OnRegisterCaps(LLUUID agentID, Caps caps)
{ {
m_log.DebugFormat("[ASTERISKVOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); m_log.DebugFormat("[ASTERISKVOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
string capsBase = "/CAPS/" + caps.CapsObjectPath; string capsBase = "/CAPS/" + caps.CapsObjectPath;
caps.RegisterHandler("ParcelVoiceInfoRequest", caps.RegisterHandler("ParcelVoiceInfoRequest",
new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
delegate(string request, string path, string param) delegate(string request, string path, string param)
{ {
return ParcelVoiceInfoRequest(request, path, param, return ParcelVoiceInfoRequest(request, path, param,
agentID, caps); agentID, caps);
})); }));
caps.RegisterHandler("ProvisionVoiceAccountRequest", caps.RegisterHandler("ProvisionVoiceAccountRequest",
new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
delegate(string request, string path, string param) delegate(string request, string path, string param)
{ {
return ProvisionVoiceAccountRequest(request, path, param, return ProvisionVoiceAccountRequest(request, path, param,
agentID, caps); agentID, caps);
})); }));
} }
/// <summary> /// <summary>
/// Callback for a client request for ParcelVoiceInfo /// Callback for a client request for ParcelVoiceInfo
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="param"></param> /// <param name="param"></param>
/// <param name="agentID"></param> /// <param name="agentID"></param>
/// <param name="caps"></param> /// <param name="caps"></param>
/// <returns></returns> /// <returns></returns>
public string ParcelVoiceInfoRequest(string request, string path, string param, public string ParcelVoiceInfoRequest(string request, string path, string param,
LLUUID agentID, Caps caps) LLUUID agentID, Caps caps)
{ {
// we need to do: // we need to do:
// - send channel_uri: as "sip:regionID@m_sipDomain" // - send channel_uri: as "sip:regionID@m_sipDomain"
try try
{ {
m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}",
request, path, param); request, path, param);
// setup response to client // setup response to client
Hashtable creds = new Hashtable(); Hashtable creds = new Hashtable();
creds["channel_uri"] = String.Format("sip:{0}@{1}", creds["channel_uri"] = String.Format("sip:{0}@{1}",
m_scene.RegionInfo.RegionID, m_sipDomain); m_scene.RegionInfo.RegionID, m_sipDomain);
string regionName = m_scene.RegionInfo.RegionName; string regionName = m_scene.RegionInfo.RegionName;
ScenePresence avatar = m_scene.GetScenePresence(agentID); ScenePresence avatar = m_scene.GetScenePresence(agentID);
if (null == m_scene.LandChannel) throw new Exception("land data not yet available"); if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
LLSDParcelVoiceInfoResponse parcelVoiceInfo = LLSDParcelVoiceInfoResponse parcelVoiceInfo =
new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds); new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds);
string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
// update region on asterisk-opensim frontend // update region on asterisk-opensim frontend
Hashtable requestData = new Hashtable(); Hashtable requestData = new Hashtable();
requestData["admin_password"] = m_asterisk_password; requestData["admin_password"] = m_asterisk_password;
requestData["region"] = m_scene.RegionInfo.RegionID.ToString(); requestData["region"] = m_scene.RegionInfo.RegionID.ToString();
if (!String.IsNullOrEmpty(m_confDomain)) if (!String.IsNullOrEmpty(m_confDomain))
{ {
requestData["region"] += String.Format("@{0}", m_confDomain); requestData["region"] += String.Format("@{0}", m_confDomain);
} }
ArrayList SendParams = new ArrayList(); ArrayList SendParams = new ArrayList();
SendParams.Add(requestData); SendParams.Add(requestData);
XmlRpcRequest updateAccountRequest = new XmlRpcRequest("region_update", SendParams); XmlRpcRequest updateAccountRequest = new XmlRpcRequest("region_update", SendParams);
XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout); XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
Hashtable responseData = (Hashtable)updateAccountResponse.Value; Hashtable responseData = (Hashtable)updateAccountResponse.Value;
if (!responseData.ContainsKey("success")) throw new Exception("region_update call failed"); if (!responseData.ContainsKey("success")) throw new Exception("region_update call failed");
bool success = Convert.ToBoolean((string)responseData["success"]); bool success = Convert.ToBoolean((string)responseData["success"]);
if (!success) throw new Exception("region_update failed"); if (!success) throw new Exception("region_update failed");
m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: {0}", r); m_log.DebugFormat("[ASTERISKVOICE][PARCELVOICE]: {0}", r);
return r; return r;
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0}, retry later", e.Message); m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0}, retry later", e.Message);
m_log.DebugFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0} failed", e.ToString()); m_log.DebugFormat("[ASTERISKVOICE][CAPS][PARCELVOICE]: {0} failed", e.ToString());
return "<llsd>undef</llsd>"; return "<llsd>undef</llsd>";
} }
} }
/// <summary> /// <summary>
/// Callback for a client request for Voice Account Details /// Callback for a client request for Voice Account Details
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="param"></param> /// <param name="param"></param>
/// <param name="agentID"></param> /// <param name="agentID"></param>
/// <param name="caps"></param> /// <param name="caps"></param>
/// <returns></returns> /// <returns></returns>
public string ProvisionVoiceAccountRequest(string request, string path, string param, public string ProvisionVoiceAccountRequest(string request, string path, string param,
LLUUID agentID, Caps caps) LLUUID agentID, Caps caps)
{ {
// we need to // we need to
// - get user data from UserProfileCacheService // - get user data from UserProfileCacheService
// - generate nonce for user voice account password // - generate nonce for user voice account password
// - issue XmlRpc request to asterisk opensim front end: // - issue XmlRpc request to asterisk opensim front end:
// + user: base 64 encoded user name (otherwise SL // + user: base 64 encoded user name (otherwise SL
// client is unhappy) // client is unhappy)
// + password: nonce // + password: nonce
// - the XmlRpc call to asteris-opensim was successful: // - the XmlRpc call to asteris-opensim was successful:
// send account details back to client // send account details back to client
try try
{ {
m_log.DebugFormat("[ASTERISKVOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", m_log.DebugFormat("[ASTERISKVOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
request, path, param); request, path, param);
// get user data & prepare voice account response // get user data & prepare voice account response
string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes()); string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
voiceUser = voiceUser.Replace('+', '-').Replace('/', '_'); voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
if (null == userInfo) throw new Exception("cannot get user details"); if (null == userInfo) throw new Exception("cannot get user details");
// we generate a nonce everytime // we generate a nonce everytime
string voicePassword = "$1$" + Util.Md5Hash(DateTime.UtcNow.ToLongTimeString() + m_asterisk_salt); string voicePassword = "$1$" + Util.Md5Hash(DateTime.UtcNow.ToLongTimeString() + m_asterisk_salt);
LLSDVoiceAccountResponse voiceAccountResponse = LLSDVoiceAccountResponse voiceAccountResponse =
new LLSDVoiceAccountResponse(voiceUser, voicePassword); new LLSDVoiceAccountResponse(voiceUser, voicePassword);
string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r); m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
// update user account on asterisk frontend // update user account on asterisk frontend
Hashtable requestData = new Hashtable(); Hashtable requestData = new Hashtable();
requestData["admin_password"] = m_asterisk_password; requestData["admin_password"] = m_asterisk_password;
requestData["username"] = voiceUser; requestData["username"] = voiceUser;
if (!String.IsNullOrEmpty(m_sipDomain)) if (!String.IsNullOrEmpty(m_sipDomain))
{ {
requestData["username"] += String.Format("@{0}", m_sipDomain); requestData["username"] += String.Format("@{0}", m_sipDomain);
} }
requestData["password"] = voicePassword; requestData["password"] = voicePassword;
ArrayList SendParams = new ArrayList(); ArrayList SendParams = new ArrayList();
SendParams.Add(requestData); SendParams.Add(requestData);
XmlRpcRequest updateAccountRequest = new XmlRpcRequest("account_update", SendParams); XmlRpcRequest updateAccountRequest = new XmlRpcRequest("account_update", SendParams);
XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout); XmlRpcResponse updateAccountResponse = updateAccountRequest.Send(m_asterisk, m_asterisk_timeout);
Hashtable responseData = (Hashtable)updateAccountResponse.Value; Hashtable responseData = (Hashtable)updateAccountResponse.Value;
if (!responseData.ContainsKey("success")) throw new Exception("account_update call failed"); if (!responseData.ContainsKey("success")) throw new Exception("account_update call failed");
bool success = Convert.ToBoolean((string)responseData["success"]); bool success = Convert.ToBoolean((string)responseData["success"]);
if (!success) throw new Exception("account_update failed"); if (!success) throw new Exception("account_update failed");
return r; return r;
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0}, retry later", e.Message); m_log.ErrorFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
m_log.DebugFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0} failed", e.ToString()); m_log.DebugFormat("[ASTERISKVOICE][CAPS][PROVISIONVOICE]: {0} failed", e.ToString());
return "<llsd>undef</llsd>"; return "<llsd>undef</llsd>";
} }
} }
} }
} }

View File

@ -1,197 +1,197 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections; using System.Collections;
using System.Reflection; using System.Reflection;
using libsecondlife; using libsecondlife;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Servers; using OpenSim.Framework.Servers;
using OpenSim.Region.Capabilities; using OpenSim.Region.Capabilities;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using Caps=OpenSim.Region.Capabilities.Caps; using Caps=OpenSim.Region.Capabilities.Caps;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Avatar.Voice.SIPVoice
{ {
public class VoiceModule : IRegionModule public class SIPVoiceModule : IRegionModule
{ {
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
private IConfig m_config; private IConfig m_config;
private string m_sipDomain; private string m_sipDomain;
private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; private static readonly string m_parcelVoiceInfoRequestPath = "0007/";
private static readonly string m_provisionVoiceAccountRequestPath = "0008/"; private static readonly string m_provisionVoiceAccountRequestPath = "0008/";
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
m_scene = scene; m_scene = scene;
m_config = config.Configs["Voice"]; m_config = config.Configs["Voice"];
if (null == m_config || !m_config.GetBoolean("enabled", false)) if (null == m_config || !m_config.GetBoolean("enabled", false))
{ {
m_log.Info("[VOICE] plugin disabled"); m_log.Info("[VOICE] plugin disabled");
return; return;
} }
m_log.Info("[VOICE] plugin enabled"); m_log.Info("[VOICE] plugin enabled");
m_sipDomain = m_config.GetString("sip_domain", String.Empty); m_sipDomain = m_config.GetString("sip_domain", String.Empty);
if (String.IsNullOrEmpty(m_sipDomain)) if (String.IsNullOrEmpty(m_sipDomain))
{ {
m_log.Error("[VOICE] plugin mis-configured: missing sip_domain configuration"); m_log.Error("[VOICE] plugin mis-configured: missing sip_domain configuration");
m_log.Info("[VOICE] plugin disabled"); m_log.Info("[VOICE] plugin disabled");
return; return;
} }
m_log.InfoFormat("[VOICE] using SIP domain {0}", m_sipDomain); m_log.InfoFormat("[VOICE] using SIP domain {0}", m_sipDomain);
scene.EventManager.OnRegisterCaps += OnRegisterCaps; scene.EventManager.OnRegisterCaps += OnRegisterCaps;
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "VoiceModule"; } get { return "VoiceModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return false; } get { return false; }
} }
public void OnRegisterCaps(LLUUID agentID, Caps caps) public void OnRegisterCaps(LLUUID agentID, Caps caps)
{ {
m_log.DebugFormat("[VOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps); m_log.DebugFormat("[VOICE] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
string capsBase = "/CAPS/" + caps.CapsObjectPath; string capsBase = "/CAPS/" + caps.CapsObjectPath;
caps.RegisterHandler("ParcelVoiceInfoRequest", caps.RegisterHandler("ParcelVoiceInfoRequest",
new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath, new RestStreamHandler("POST", capsBase + m_parcelVoiceInfoRequestPath,
delegate(string request, string path, string param) delegate(string request, string path, string param)
{ {
return ParcelVoiceInfoRequest(request, path, param, return ParcelVoiceInfoRequest(request, path, param,
agentID, caps); agentID, caps);
})); }));
caps.RegisterHandler("ProvisionVoiceAccountRequest", caps.RegisterHandler("ProvisionVoiceAccountRequest",
new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath, new RestStreamHandler("POST", capsBase + m_provisionVoiceAccountRequestPath,
delegate(string request, string path, string param) delegate(string request, string path, string param)
{ {
return ProvisionVoiceAccountRequest(request, path, param, return ProvisionVoiceAccountRequest(request, path, param,
agentID, caps); agentID, caps);
})); }));
} }
/// <summary> /// <summary>
/// Callback for a client request for ParcelVoiceInfo /// Callback for a client request for ParcelVoiceInfo
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="param"></param> /// <param name="param"></param>
/// <param name="agentID"></param> /// <param name="agentID"></param>
/// <param name="caps"></param> /// <param name="caps"></param>
/// <returns></returns> /// <returns></returns>
public string ParcelVoiceInfoRequest(string request, string path, string param, public string ParcelVoiceInfoRequest(string request, string path, string param,
LLUUID agentID, Caps caps) LLUUID agentID, Caps caps)
{ {
try try
{ {
m_log.DebugFormat("[VOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", request, path, param); m_log.DebugFormat("[VOICE][PARCELVOICE]: request: {0}, path: {1}, param: {2}", request, path, param);
// FIXME: get the creds from region file or from config // FIXME: get the creds from region file or from config
Hashtable creds = new Hashtable(); Hashtable creds = new Hashtable();
creds["channel_uri"] = String.Format("sip:{0}@{1}", agentID.ToString(), m_sipDomain); creds["channel_uri"] = String.Format("sip:{0}@{1}", agentID, m_sipDomain);
string regionName = m_scene.RegionInfo.RegionName; string regionName = m_scene.RegionInfo.RegionName;
ScenePresence avatar = m_scene.GetScenePresence(agentID); ScenePresence avatar = m_scene.GetScenePresence(agentID);
if (null == m_scene.LandChannel) throw new Exception("land data not yet available"); if (null == m_scene.LandChannel) throw new Exception("land data not yet available");
LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); LandData land = m_scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
LLSDParcelVoiceInfoResponse parcelVoiceInfo = LLSDParcelVoiceInfoResponse parcelVoiceInfo =
new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds); new LLSDParcelVoiceInfoResponse(regionName, land.localID, creds);
string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
m_log.DebugFormat("[VOICE][PARCELVOICE]: {0}", r); m_log.DebugFormat("[VOICE][PARCELVOICE]: {0}", r);
return r; return r;
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[CAPS]: {0}, try again later", e.ToString()); m_log.ErrorFormat("[CAPS]: {0}, try again later", e.ToString());
} }
return null; return null;
} }
/// <summary> /// <summary>
/// Callback for a client request for Voice Account Details /// Callback for a client request for Voice Account Details
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="param"></param> /// <param name="param"></param>
/// <param name="agentID"></param> /// <param name="agentID"></param>
/// <param name="caps"></param> /// <param name="caps"></param>
/// <returns></returns> /// <returns></returns>
public string ProvisionVoiceAccountRequest(string request, string path, string param, public string ProvisionVoiceAccountRequest(string request, string path, string param,
LLUUID agentID, Caps caps) LLUUID agentID, Caps caps)
{ {
try try
{ {
m_log.DebugFormat("[VOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", m_log.DebugFormat("[VOICE][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
request, path, param); request, path, param);
string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes()); string voiceUser = "x" + Convert.ToBase64String(agentID.GetBytes());
voiceUser = voiceUser.Replace('+', '-').Replace('/', '_'); voiceUser = voiceUser.Replace('+', '-').Replace('/', '_');
CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID); CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(agentID);
if (null == userInfo) throw new Exception("cannot get user details"); if (null == userInfo) throw new Exception("cannot get user details");
LLSDVoiceAccountResponse voiceAccountResponse = LLSDVoiceAccountResponse voiceAccountResponse =
new LLSDVoiceAccountResponse(voiceUser, "$1$" + userInfo.UserProfile.PasswordHash); new LLSDVoiceAccountResponse(voiceUser, "$1$" + userInfo.UserProfile.PasswordHash);
string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r); m_log.DebugFormat("[CAPS][PROVISIONVOICE]: {0}", r);
return r; return r;
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[CAPS][PROVISIONVOICE]: {0}, retry later", e.Message); m_log.ErrorFormat("[CAPS][PROVISIONVOICE]: {0}, retry later", e.Message);
} }
return null; return null;
} }
} }
} }

View File

@ -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
}
}

View File

@ -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>(T e);
bool HasInterface<T>(Location loc);
T RequestInterface<T>(Location loc);
T[] RequestInterface<T>();
Location GetLocationByDirection(Scene scene, InterregionModule.Direction dir);
void internal_CreateRemotingObjects();
}
}

View File

@ -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<Type, Object> m_interfaces = new Dictionary<Type, object>();
private readonly List<Location> m_myLocations = new List<Location>();
private readonly Dictionary<Location, string[]> m_neighbourInterfaces = new Dictionary<Location, string[]>();
private readonly Dictionary<Location, RemotingObject> m_neighbourRemote = new Dictionary<Location, RemotingObject>();
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<IInterregionModule>(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>(T e)
{
m_interfaces[typeof (T)] = e;
}
public bool HasInterface<T>(Location loc)
{
foreach (string val in m_neighbourInterfaces[loc])
{
if (val == typeof (T).FullName)
{
return true;
}
}
return false;
}
public T RequestInterface<T>(Location loc)
{
if (m_neighbourRemote.ContainsKey(loc))
{
return m_neighbourRemote[loc].RequestInterface<T>();
}
else
{
throw new IndexOutOfRangeException("No neighbour availible at that location");
}
}
public T[] RequestInterface<T>()
{
List<T> m_t = new List<T>();
foreach (RemotingObject remote in m_neighbourRemote.Values)
{
try
{
m_t.Add(remote.RequestInterface<T>());
}
catch (NotSupportedException)
{
}
}
return m_t.ToArray();
}
public Location GetLocationByDirection(Scene scene, Direction dir)
{
return new Location(0, 0);
}
}
}

View File

@ -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<Type, Object> m_interfaces = new Dictionary<Type, object>();
public RemotingObject(Dictionary<Type, Object> 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<Type, object> pair in m_interfaces)
{
interfaces[i++] = pair.Key.FullName;
}
return interfaces;
}
/// <summary>
/// Returns a registered interface availible to neighbouring regions.
/// </summary>
/// <typeparam name="T">The type of interface you wish to request</typeparam>
/// <returns>A MarshalByRefObject inherited from this region inheriting the interface requested.</returns>
/// <remarks>All registered interfaces <b>MUST</b> inherit from MarshalByRefObject and use only serialisable types.</remarks>
public T RequestInterface<T>()
{
if (m_interfaces.ContainsKey(typeof (T)))
return (T) m_interfaces[typeof (T)];
throw new NotSupportedException("No such interface registered.");
}
}
}

View File

@ -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
{
}
}

View File

@ -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<Scene> m_regions = new List<Scene>();
private string m_savedir = "exports" + "/";
private List<IFileSerialiser> m_serialisers = new List<IFileSerialiser>();
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource source)
{
scene.RegisterModuleCommander("Export", m_commander);
scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
scene.RegisterModuleInterface<IRegionSerialiser>(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<string> SerialiseRegion(Scene scene, string saveDir)
{
List<string> results = new List<string>();
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<string> results = SerialiseRegion(region, m_savedir + region.RegionInfo.RegionID.ToString() + "/");
}
}
}
private void InterfaceSaveAllRegions(Object[] args)
{
foreach (Scene region in m_regions)
{
List<string> 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);
}
}
}

View File

@ -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);
}
}

View File

@ -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<string> SerialiseRegion(Scene scene, string saveDir);
}
}

View File

@ -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 = "<scene>";
List<EntityBase> EntityList = scene.GetEntities();
List<string> EntityXml = new List<string>();
foreach (EntityBase ent in EntityList)
{
if (ent is SceneObjectGroup)
{
EntityXml.Add(((SceneObjectGroup) ent).ToXmlString2());
}
}
EntityXml.Sort();
foreach (string xml in EntityXml)
xmlstream += xml;
xmlstream += "</scene>";
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
}
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
/// <summary>
/// Keeps track of a specific piece of land's information
/// </summary>
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<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
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
/// <summary>
/// Checks to see if this land object contains a point
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns>Returns true if the piece of land contains the specified point</returns>
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
/// <summary>
/// Sends land properties as requested
/// </summary>
/// <param name="sequence_id">ID sent by client for them to keep track of</param>
/// <param name="snap_selection">Bool sent by client for them to use</param>
/// <param name="remote_client">Object representing the client</param>
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<ScenePresence> 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<ParcelAccessListReplyPacket.ListBlock> list = new List<ParcelAccessListReplyPacket.ListBlock>();
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<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client)
{
LandData newData = landData.Copy();
if (entries.Count == 1 && entries[0].AgentID == LLUUID.Zero)
{
entries.Clear();
}
List<ParcelManager.ParcelAccessEntry> toRemove = new List<ParcelManager.ParcelAccessEntry>();
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
/// <summary>
/// Updates the AABBMin and AABBMax values after area/shape modification of the land object
/// </summary>
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();
}
/// <summary>
/// Update all settings in land such as area, bitmap byte array, etc
/// </summary>
public void forceUpdateLandInfo()
{
updateAABBAndAreaValues();
updateLandBitmapByteArray();
}
public void setLandBitmapFromByteArray()
{
landBitmap = convertBytesToLandBitmap();
}
#endregion
#region Land Bitmap Functions
/// <summary>
/// Sets the land's bitmap manually
/// </summary>
/// <param name="bitmap">64x64 block representing where this land is on a map</param>
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();
}
}
/// <summary>
/// Gets the land's bitmap manually
/// </summary>
/// <returns></returns>
public bool[,] getLandBitmap()
{
return landBitmap;
}
/// <summary>
/// Converts the land bitmap to a packet friendly byte array
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// Full sim land object creation
/// </summary>
/// <returns></returns>
public bool[,] basicFullRegionLandBitmap()
{
return getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize);
}
/// <summary>
/// Used to modify the bitmap between the x and y points. Points use 64 scale
/// </summary>
/// <param name="start_x"></param>
/// <param name="start_y"></param>
/// <param name="end_x"></param>
/// <param name="end_y"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Change a land bitmap at within a square and set those points to a specific value
/// </summary>
/// <param name="land_bitmap"></param>
/// <param name="start_x"></param>
/// <param name="start_y"></param>
/// <param name="end_x"></param>
/// <param name="end_y"></param>
/// <param name="set_value"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Join the true values of 2 bitmaps together
/// </summary>
/// <param name="bitmap_base"></param>
/// <param name="bitmap_add"></param>
/// <returns></returns>
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<uint> resultLocalIDs = new List<uint>();
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);
}
}
/// <summary>
/// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes
/// aggreagete details such as the number of prims.
///
/// </summary>
/// <param name="remote_client">
/// A <see cref="IClientAPI"/>
/// </param>
public void sendLandObjectOwners(IClientAPI remote_client)
{
Dictionary<LLUUID, int> primCount = new Dictionary<LLUUID, int>();
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<LLUUID, int> getLandObjectOwners()
{
Dictionary<LLUUID, int> ownersAndCount = new Dictionary<LLUUID, int>();
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
}

View File

@ -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
{
/// <summary>
/// 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
/// </summary>
public class Command : ICommand
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<CommandArgument> m_args = new List<CommandArgument>();
private Action<object[]> m_command;
private string m_help;
private string m_name;
public Command(string name, Action<Object[]> 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<string, string> Arguments
{
get
{
Dictionary<string, string> tmp = new Dictionary<string, string>();
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 '<module> <command> 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
}
/// <summary>
/// A single command argument, contains name, type and at runtime, value.
/// </summary>
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; }
}
}
/// <summary>
/// A class to enable modules to register console and script commands, which enforces typing and valid input.
/// </summary>
public class Commander : ICommander
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<string, ICommand> m_commands = new Dictionary<string, ICommand>();
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;
}
/// <summary>
/// Generates a runtime C# class which can be compiled and inserted via reflection to enable modules to register new script commands
/// </summary>
/// <returns>Returns C# source code to create a binding</returns>
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<string, string> 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<string, string> 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;
}
/// <summary>
/// Runs a specified function with attached arguments
/// *** <b>DO NOT CALL DIRECTLY.</b> ***
/// Call ProcessConsoleCommand instead if handling human input.
/// </summary>
/// <param name="function">The function name to call</param>
/// <param name="args">The function parameters</param>
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();
}
}
}

View File

@ -1,277 +1,277 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using libsecondlife; using libsecondlife;
using Nini.Config; using Nini.Config;
using OpenJPEGNet; using OpenJPEGNet;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Scripting.DynamicTexture
{ {
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
{ {
private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>(); private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
private Dictionary<string, IDynamicTextureRender> RenderPlugins = private Dictionary<string, IDynamicTextureRender> RenderPlugins =
new Dictionary<string, IDynamicTextureRender>(); new Dictionary<string, IDynamicTextureRender>();
private Dictionary<LLUUID, DynamicTextureUpdater> Updaters = new Dictionary<LLUUID, DynamicTextureUpdater>(); private Dictionary<LLUUID, DynamicTextureUpdater> Updaters = new Dictionary<LLUUID, DynamicTextureUpdater>();
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{ {
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
scene.RegisterModuleInterface<IDynamicTextureManager>(this); scene.RegisterModuleInterface<IDynamicTextureManager>(this);
} }
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return "DynamicTextureModule"; } get { return "DynamicTextureModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return true; } get { return true; }
} }
public void RegisterRender(string handleType, IDynamicTextureRender render) public void RegisterRender(string handleType, IDynamicTextureRender render)
{ {
if (!RenderPlugins.ContainsKey(handleType)) if (!RenderPlugins.ContainsKey(handleType))
{ {
RenderPlugins.Add(handleType, render); RenderPlugins.Add(handleType, render);
} }
} }
public void ReturnData(LLUUID id, byte[] data) public void ReturnData(LLUUID id, byte[] data)
{ {
if (Updaters.ContainsKey(id)) if (Updaters.ContainsKey(id))
{ {
DynamicTextureUpdater updater = Updaters[id]; DynamicTextureUpdater updater = Updaters[id];
if (RegisteredScenes.ContainsKey(updater.SimUUID)) if (RegisteredScenes.ContainsKey(updater.SimUUID))
{ {
Scene scene = RegisteredScenes[updater.SimUUID]; Scene scene = RegisteredScenes[updater.SimUUID];
updater.DataReceived(data, scene); updater.DataReceived(data, scene);
} }
} }
} }
public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url,
string extraParams, int updateTimer) string extraParams, int updateTimer)
{ {
return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255);
} }
public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url,
string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
{ {
if (RenderPlugins.ContainsKey(contentType)) if (RenderPlugins.ContainsKey(contentType))
{ {
//Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType); //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType);
DynamicTextureUpdater updater = new DynamicTextureUpdater(); DynamicTextureUpdater updater = new DynamicTextureUpdater();
updater.SimUUID = simID; updater.SimUUID = simID;
updater.PrimID = primID; updater.PrimID = primID;
updater.ContentType = contentType; updater.ContentType = contentType;
updater.Url = url; updater.Url = url;
updater.UpdateTimer = updateTimer; updater.UpdateTimer = updateTimer;
updater.UpdaterID = LLUUID.Random(); updater.UpdaterID = LLUUID.Random();
updater.Params = extraParams; updater.Params = extraParams;
updater.BlendWithOldTexture = SetBlending; updater.BlendWithOldTexture = SetBlending;
updater.FrontAlpha = AlphaValue; updater.FrontAlpha = AlphaValue;
if (!Updaters.ContainsKey(updater.UpdaterID)) if (!Updaters.ContainsKey(updater.UpdaterID))
{ {
Updaters.Add(updater.UpdaterID, updater); Updaters.Add(updater.UpdaterID, updater);
} }
RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
return updater.UpdaterID; return updater.UpdaterID;
} }
return LLUUID.Zero; return LLUUID.Zero;
} }
public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data,
string extraParams, int updateTimer) string extraParams, int updateTimer)
{ {
return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255);
} }
public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data,
string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
{ {
if (RenderPlugins.ContainsKey(contentType)) if (RenderPlugins.ContainsKey(contentType))
{ {
DynamicTextureUpdater updater = new DynamicTextureUpdater(); DynamicTextureUpdater updater = new DynamicTextureUpdater();
updater.SimUUID = simID; updater.SimUUID = simID;
updater.PrimID = primID; updater.PrimID = primID;
updater.ContentType = contentType; updater.ContentType = contentType;
updater.BodyData = data; updater.BodyData = data;
updater.UpdateTimer = updateTimer; updater.UpdateTimer = updateTimer;
updater.UpdaterID = LLUUID.Random(); updater.UpdaterID = LLUUID.Random();
updater.Params = extraParams; updater.Params = extraParams;
updater.BlendWithOldTexture = SetBlending; updater.BlendWithOldTexture = SetBlending;
updater.FrontAlpha = AlphaValue; updater.FrontAlpha = AlphaValue;
if (!Updaters.ContainsKey(updater.UpdaterID)) if (!Updaters.ContainsKey(updater.UpdaterID))
{ {
Updaters.Add(updater.UpdaterID, updater); Updaters.Add(updater.UpdaterID, updater);
} }
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
return updater.UpdaterID; return updater.UpdaterID;
} }
return LLUUID.Zero; return LLUUID.Zero;
} }
public class DynamicTextureUpdater public class DynamicTextureUpdater
{ {
public LLUUID SimUUID; public LLUUID SimUUID;
public LLUUID UpdaterID; public LLUUID UpdaterID;
public string ContentType; public string ContentType;
public string Url; public string Url;
public string BodyData; public string BodyData;
public LLUUID PrimID; public LLUUID PrimID;
public int UpdateTimer; public int UpdateTimer;
public LLUUID LastAssetID; public LLUUID LastAssetID;
public string Params; public string Params;
public bool BlendWithOldTexture = false; public bool BlendWithOldTexture = false;
public bool SetNewFrontAlpha = false; public bool SetNewFrontAlpha = false;
public byte FrontAlpha = 255; public byte FrontAlpha = 255;
public DynamicTextureUpdater() public DynamicTextureUpdater()
{ {
LastAssetID = LLUUID.Zero; LastAssetID = LLUUID.Zero;
UpdateTimer = 0; UpdateTimer = 0;
BodyData = null; BodyData = null;
} }
public void DataReceived(byte[] data, Scene scene) public void DataReceived(byte[] data, Scene scene)
{ {
SceneObjectPart part = scene.GetSceneObjectPart(PrimID); SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
byte[] assetData; byte[] assetData;
AssetBase oldAsset = null; AssetBase oldAsset = null;
if (BlendWithOldTexture) if (BlendWithOldTexture)
{ {
LLUUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID; LLUUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID;
oldAsset = scene.AssetCache.GetAsset(lastTextureID, true); oldAsset = scene.AssetCache.GetAsset(lastTextureID, true);
if (oldAsset != null) if (oldAsset != null)
{ {
assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha);
} }
else else
{ {
assetData = new byte[data.Length]; assetData = new byte[data.Length];
Array.Copy(data, assetData, data.Length); Array.Copy(data, assetData, data.Length);
} }
} }
else else
{ {
assetData = new byte[data.Length]; assetData = new byte[data.Length];
Array.Copy(data, assetData, data.Length); Array.Copy(data, assetData, data.Length);
} }
//TODO delete the last asset(data), if it was a dynamic texture //TODO delete the last asset(data), if it was a dynamic texture
AssetBase asset = new AssetBase(); AssetBase asset = new AssetBase();
asset.FullID = LLUUID.Random(); asset.FullID = LLUUID.Random();
asset.Data = assetData; asset.Data = assetData;
asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000);
asset.Type = 0; asset.Type = 0;
asset.Description = "dynamic image"; asset.Description = "dynamic image";
asset.Local = false; asset.Local = false;
asset.Temporary = true; asset.Temporary = true;
scene.AssetCache.AddAsset(asset); scene.AssetCache.AddAsset(asset);
LastAssetID = asset.FullID; LastAssetID = asset.FullID;
part.Shape.Textures = new LLObject.TextureEntry(asset.FullID); part.Shape.Textures = new LLObject.TextureEntry(asset.FullID);
part.ScheduleFullUpdate(); part.ScheduleFullUpdate();
} }
// TODO: unused // TODO: unused
// private byte[] BlendTextures(byte[] frontImage, byte[] backImage) // private byte[] BlendTextures(byte[] frontImage, byte[] backImage)
// { // {
// return BlendTextures(frontImage, backImage, false, 0); // return BlendTextures(frontImage, backImage, false, 0);
// } // }
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
{ {
Bitmap image1 = new Bitmap(OpenJPEG.DecodeToImage(frontImage)); Bitmap image1 = new Bitmap(OpenJPEG.DecodeToImage(frontImage));
Bitmap image2 = new Bitmap(OpenJPEG.DecodeToImage(backImage)); Bitmap image2 = new Bitmap(OpenJPEG.DecodeToImage(backImage));
if (setNewAlpha) if (setNewAlpha)
{ {
SetAlpha(ref image1, newAlpha); SetAlpha(ref image1, newAlpha);
} }
Bitmap joint = MergeBitMaps(image1, image2); Bitmap joint = MergeBitMaps(image1, image2);
return OpenJPEG.EncodeFromImage(joint, true); return OpenJPEG.EncodeFromImage(joint, true);
} }
public Bitmap MergeBitMaps(Bitmap front, Bitmap back) public Bitmap MergeBitMaps(Bitmap front, Bitmap back)
{ {
Bitmap joint; Bitmap joint;
Graphics jG; Graphics jG;
joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb); joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb);
jG = Graphics.FromImage(joint); jG = Graphics.FromImage(joint);
jG.DrawImage(back, 0, 0, back.Width, back.Height); jG.DrawImage(back, 0, 0, back.Width, back.Height);
jG.DrawImage(front, 0, 0, back.Width, back.Height); jG.DrawImage(front, 0, 0, back.Width, back.Height);
return joint; return joint;
} }
private void SetAlpha(ref Bitmap b, byte alpha) private void SetAlpha(ref Bitmap b, byte alpha)
{ {
for (int w = 0; w < b.Width; w++) for (int w = 0; w < b.Width; w++)
{ {
for (int h = 0; h < b.Height; h++) for (int h = 0; h < b.Height; h++)
{ {
b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h))); b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h)));
} }
} }
} }
} }
} }
} }

View File

@ -1,364 +1,356 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using libsecondlife; using libsecondlife;
using Nini.Config; using Nini.Config;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
/***************************************************** /*****************************************************
* *
* ScriptsHttpRequests * ScriptsHttpRequests
* *
* Implements the llHttpRequest and http_response * Implements the llHttpRequest and http_response
* callback. * callback.
* *
* Some stuff was already in LSLLongCmdHandler, and then * Some stuff was already in LSLLongCmdHandler, and then
* there was this file with a stub class in it. So, * there was this file with a stub class in it. So,
* I am moving some of the objects and functions out of * I am moving some of the objects and functions out of
* LSLLongCmdHandler, such as the HttpRequestClass, the * LSLLongCmdHandler, such as the HttpRequestClass, the
* start and stop methods, and setting up pending and * start and stop methods, and setting up pending and
* completed queues. These are processed in the * completed queues. These are processed in the
* LSLLongCmdHandler polling loop. Similiar to the * LSLLongCmdHandler polling loop. Similiar to the
* XMLRPCModule, since that seems to work. * XMLRPCModule, since that seems to work.
* *
* //TODO * //TODO
* *
* This probably needs some throttling mechanism but * This probably needs some throttling mechanism but
* its wide open right now. This applies to both * its wide open right now. This applies to both
* number of requests and data volume. * number of requests and data volume.
* *
* Linden puts all kinds of header fields in the requests. * Linden puts all kinds of header fields in the requests.
* Not doing any of that: * Not doing any of that:
* User-Agent * User-Agent
* X-SecondLife-Shard * X-SecondLife-Shard
* X-SecondLife-Object-Name * X-SecondLife-Object-Name
* X-SecondLife-Object-Key * X-SecondLife-Object-Key
* X-SecondLife-Region * X-SecondLife-Region
* X-SecondLife-Local-Position * X-SecondLife-Local-Position
* X-SecondLife-Local-Velocity * X-SecondLife-Local-Velocity
* X-SecondLife-Local-Rotation * X-SecondLife-Local-Rotation
* X-SecondLife-Owner-Name * X-SecondLife-Owner-Name
* X-SecondLife-Owner-Key * X-SecondLife-Owner-Key
* *
* HTTPS support * HTTPS support
* *
* Configurable timeout? * Configurable timeout?
* Configurable max repsonse size? * Configurable max repsonse size?
* Configurable * Configurable
* *
* **************************************************/ * **************************************************/
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest
{ {
public class ScriptHTTPRequests : IRegionModule, IHttpRequests public class HttpRequestModule : IRegionModule, IHttpRequests
{ {
private Scene m_scene; private Scene m_scene;
private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
private object HttpListLock = new object(); private object HttpListLock = new object();
private string m_name = "HttpScriptRequests"; private string m_name = "HttpScriptRequests";
private int httpTimeout = 30000; private int httpTimeout = 30000;
// <request id, HttpRequestClass> // <request id, HttpRequestClass>
private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests; private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests;
public ScriptHTTPRequests() public HttpRequestModule()
{ {
} }
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
m_scene = scene; m_scene = scene;
m_scene.RegisterModuleInterface<IHttpRequests>(this); m_scene.RegisterModuleInterface<IHttpRequests>(this);
m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>(); m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>();
} }
public void PostInitialise() public void PostInitialise()
{ {
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return m_name; } get { return m_name; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return true; } get { return true; }
} }
public LLUUID MakeHttpRequest(string url, string parameters, string body) public LLUUID MakeHttpRequest(string url, string parameters, string body)
{ {
return LLUUID.Zero; return LLUUID.Zero;
} }
public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body) public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body)
{ {
LLUUID reqID = LLUUID.Random(); LLUUID reqID = LLUUID.Random();
HttpRequestClass htc = new HttpRequestClass(); HttpRequestClass htc = new HttpRequestClass();
// Partial implementation: support for parameter flags needed // Partial implementation: support for parameter flags needed
// see http://wiki.secondlife.com/wiki/LlHTTPRequest // see http://wiki.secondlife.com/wiki/LlHTTPRequest
// //
// Parameters are expected in {key, value, ... , key, value} // Parameters are expected in {key, value, ... , key, value}
if (parameters != null) if (parameters != null)
{ {
string[] parms = parameters.ToArray(); string[] parms = parameters.ToArray();
for (int i = 0; i < parms.Length/2; i += 2) for (int i = 0; i < parms.Length/2; i += 2)
{ {
switch (Int32.Parse(parms[i])) switch (Int32.Parse(parms[i]))
{ {
case HttpRequestClass.HTTP_METHOD: case HttpRequestClass.HTTP_METHOD:
htc.httpMethod = parms[i + 1]; htc.httpMethod = parms[i + 1];
break; break;
case HttpRequestClass.HTTP_MIMETYPE: case HttpRequestClass.HTTP_MIMETYPE:
htc.httpMIMEType = parms[i + 1]; htc.httpMIMEType = parms[i + 1];
break; break;
case HttpRequestClass.HTTP_BODY_MAXLENGTH: case HttpRequestClass.HTTP_BODY_MAXLENGTH:
// TODO implement me // TODO implement me
break; break;
case HttpRequestClass.HTTP_VERIFY_CERT: case HttpRequestClass.HTTP_VERIFY_CERT:
// TODO implement me // TODO implement me
break; break;
} }
} }
} }
htc.localID = localID; htc.localID = localID;
htc.itemID = itemID; htc.itemID = itemID;
htc.url = url; htc.url = url;
htc.reqID = reqID; htc.reqID = reqID;
htc.httpTimeout = httpTimeout; htc.httpTimeout = httpTimeout;
htc.outbound_body = body; htc.outbound_body = body;
lock (HttpListLock) lock (HttpListLock)
{ {
m_pendingRequests.Add(reqID, htc); m_pendingRequests.Add(reqID, htc);
} }
htc.process(); htc.process();
return reqID; return reqID;
} }
public void StopHttpRequest(uint m_localID, LLUUID m_itemID) public void StopHttpRequest(uint m_localID, LLUUID m_itemID)
{ {
if(m_pendingRequests != null) { if(m_pendingRequests != null) {
lock (HttpListLock) lock (HttpListLock)
{ {
HttpRequestClass tmpReq; HttpRequestClass tmpReq;
if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
{ {
tmpReq.Stop(); tmpReq.Stop();
m_pendingRequests.Remove(m_itemID); m_pendingRequests.Remove(m_itemID);
} }
} }
} }
} }
/* /*
* TODO * TODO
* Not sure how important ordering is is here - the next first * Not sure how important ordering is is here - the next first
* one completed in the list is returned, based soley on its list * one completed in the list is returned, based soley on its list
* position, not the order in which the request was started or * position, not the order in which the request was started or
* finsihed. I thought about setting up a queue for this, but * finsihed. I thought about setting up a queue for this, but
* it will need some refactoring and this works 'enough' right now * it will need some refactoring and this works 'enough' right now
*/ */
public HttpRequestClass GetNextCompletedRequest() public HttpRequestClass GetNextCompletedRequest()
{ {
lock (HttpListLock) lock (HttpListLock)
{ {
foreach (LLUUID luid in m_pendingRequests.Keys) foreach (LLUUID luid in m_pendingRequests.Keys)
{ {
HttpRequestClass tmpReq; HttpRequestClass tmpReq;
if (m_pendingRequests.TryGetValue(luid, out tmpReq)) if (m_pendingRequests.TryGetValue(luid, out tmpReq))
{ {
if (tmpReq.finished) if (tmpReq.finished)
{ {
return tmpReq; return tmpReq;
} }
} }
} }
} }
return null; return null;
} }
public void RemoveCompletedRequest(LLUUID id) public void RemoveCompletedRequest(LLUUID id)
{ {
lock (HttpListLock) lock (HttpListLock)
{ {
HttpRequestClass tmpReq; HttpRequestClass tmpReq;
if (m_pendingRequests.TryGetValue(id, out tmpReq)) if (m_pendingRequests.TryGetValue(id, out tmpReq))
{ {
tmpReq.Stop(); tmpReq.Stop();
tmpReq = null; tmpReq = null;
m_pendingRequests.Remove(id); m_pendingRequests.Remove(id);
} }
} }
} }
} }
// public class HttpRequestClass
// HTTP REAQUEST {
// This class was originally in LSLLongCmdHandler // Constants for parameters
// public const int HTTP_METHOD = 0;
// TODO: setter/getter methods, maybe pass some in public const int HTTP_MIMETYPE = 1;
// constructor public const int HTTP_BODY_MAXLENGTH = 2;
// public const int HTTP_VERIFY_CERT = 3;
public class HttpRequestClass // Parameter members and default values
{ public string httpMethod = "GET";
// Constants for parameters public string httpMIMEType = "text/plain;charset=utf-8";
public const int HTTP_METHOD = 0; public int httpBodyMaxLen = 2048; // not implemented
public const int HTTP_MIMETYPE = 1; public bool httpVerifyCert = true; // not implemented
public const int HTTP_BODY_MAXLENGTH = 2;
public const int HTTP_VERIFY_CERT = 3; // Request info
public uint localID;
// Parameter members and default values public LLUUID itemID;
public string httpMethod = "GET"; public LLUUID reqID;
public string httpMIMEType = "text/plain;charset=utf-8"; public int httpTimeout;
public int httpBodyMaxLen = 2048; // not implemented public string url;
public bool httpVerifyCert = true; // not implemented public string outbound_body;
public DateTime next;
// Request info public int status;
public uint localID; public bool finished;
public LLUUID itemID; public List<string> response_metadata;
public LLUUID reqID; public string response_body;
public int httpTimeout; public HttpWebRequest request;
public string url; private Thread httpThread;
public string outbound_body;
public DateTime next; public void process()
public int status; {
public bool finished; httpThread = new Thread(SendRequest);
public List<string> response_metadata; httpThread.Name = "HttpRequestThread";
public string response_body; httpThread.Priority = ThreadPriority.BelowNormal;
public HttpWebRequest request; httpThread.IsBackground = true;
private Thread httpThread; finished = false;
httpThread.Start();
public void process() ThreadTracker.Add(httpThread);
{ }
httpThread = new Thread(SendRequest);
httpThread.Name = "HttpRequestThread"; /*
httpThread.Priority = ThreadPriority.BelowNormal; * TODO: More work on the response codes. Right now
httpThread.IsBackground = true; * returning 200 for success or 499 for exception
finished = false; */
httpThread.Start();
ThreadTracker.Add(httpThread); public void SendRequest()
} {
HttpWebResponse response = null;
/* StringBuilder sb = new StringBuilder();
* TODO: More work on the response codes. Right now byte[] buf = new byte[8192];
* returning 200 for success or 499 for exception string tempString = null;
*/ int count = 0;
public void SendRequest() try
{ {
HttpWebResponse response = null; request = (HttpWebRequest)
StringBuilder sb = new StringBuilder(); WebRequest.Create(url);
byte[] buf = new byte[8192]; request.Method = httpMethod;
string tempString = null; request.ContentType = httpMIMEType;
int count = 0;
request.Timeout = httpTimeout;
try // execute the request
{ response = (HttpWebResponse)
request = (HttpWebRequest) request.GetResponse();
WebRequest.Create(url);
request.Method = httpMethod; Stream resStream = response.GetResponseStream();
request.ContentType = httpMIMEType;
do
request.Timeout = httpTimeout; {
// execute the request // fill the buffer with data
response = (HttpWebResponse) count = resStream.Read(buf, 0, buf.Length);
request.GetResponse();
// make sure we read some data
Stream resStream = response.GetResponseStream(); if (count != 0)
{
do // translate from bytes to ASCII text
{ tempString = Encoding.UTF8.GetString(buf, 0, count);
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length); // continue building the string
sb.Append(tempString);
// make sure we read some data }
if (count != 0) } while (count > 0); // any more data to read?
{
// translate from bytes to ASCII text response_body = sb.ToString();
tempString = Encoding.UTF8.GetString(buf, 0, count); }
catch (Exception e)
// continue building the string {
sb.Append(tempString); status = 499;
} response_body = e.Message;
} while (count > 0); // any more data to read? finished = true;
return;
response_body = sb.ToString(); }
}
catch (Exception e) status = 200;
{ finished = true;
status = 499; }
response_body = e.Message;
finished = true; public void Stop()
return; {
} try
{
status = 200; httpThread.Abort();
finished = true; }
} catch (Exception)
{
public void Stop() }
{ }
try }
{ }
httpThread.Abort();
}
catch (Exception)
{
}
}
}
}

View File

@ -1,180 +1,179 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Net; using System.Net;
using libsecondlife; using libsecondlife;
using Nini.Config; using Nini.Config;
using OpenJPEGNet; using OpenJPEGNet;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Scripting.LoadImageURL
{ {
public class LoadImageURLModule : IRegionModule, IDynamicTextureRender
public class LoadImageURLModule : IRegionModule, IDynamicTextureRender {
{ private string m_name = "LoadImageURL";
private string m_name = "LoadImageURL"; private IDynamicTextureManager m_textureManager;
private IDynamicTextureManager m_textureManager; private Scene m_scene;
private Scene m_scene;
public void Initialise(Scene scene, IConfigSource config)
public void Initialise(Scene scene, IConfigSource config) {
{ if (m_scene == null)
if (m_scene == null) {
{ m_scene = scene;
m_scene = scene; }
} }
}
public void PostInitialise()
public void PostInitialise() {
{ m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>(); if (m_textureManager != null)
if (m_textureManager != null) {
{ m_textureManager.RegisterRender(GetContentType(), this);
m_textureManager.RegisterRender(GetContentType(), this); }
} }
}
public void Close()
public void Close() {
{ }
}
public string Name
public string Name {
{ get { return m_name; }
get { return m_name; } }
}
public bool IsSharedModule
public bool IsSharedModule {
{ get { return true; }
get { return true; } }
}
public string GetName()
public string GetName() {
{ return m_name;
return m_name; }
}
public string GetContentType()
public string GetContentType() {
{ return ("image");
return ("image"); }
}
public bool SupportsAsynchronous()
public bool SupportsAsynchronous() {
{ return true;
return true; }
}
public byte[] ConvertUrl(string url, string extraParams)
public byte[] ConvertUrl(string url, string extraParams) {
{ return null;
return null; }
}
public byte[] ConvertStream(Stream data, string extraParams)
public byte[] ConvertStream(Stream data, string extraParams) {
{ return null;
return null; }
}
public bool AsyncConvertUrl(LLUUID id, string url, string extraParams)
public bool AsyncConvertUrl(LLUUID id, string url, string extraParams) {
{ MakeHttpRequest(url, id);
MakeHttpRequest(url, id); return true;
return true; }
}
public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams)
public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) {
{ return false;
return false; }
}
private void MakeHttpRequest(string url, LLUUID requestID)
private void MakeHttpRequest(string url, LLUUID requestID) {
{ WebRequest request = HttpWebRequest.Create(url);
WebRequest request = HttpWebRequest.Create(url); RequestState state = new RequestState((HttpWebRequest) request, requestID);
RequestState state = new RequestState((HttpWebRequest) request, requestID); IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1)); state.TimeOfRequest = (int) t.TotalSeconds;
state.TimeOfRequest = (int) t.TotalSeconds; }
}
private void HttpRequestReturn(IAsyncResult result)
private void HttpRequestReturn(IAsyncResult result) {
{ RequestState state = (RequestState) result.AsyncState;
RequestState state = (RequestState) result.AsyncState; WebRequest request = (WebRequest) state.Request;
WebRequest request = (WebRequest) state.Request; HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result);
HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result); if (response.StatusCode == HttpStatusCode.OK)
if (response.StatusCode == HttpStatusCode.OK) {
{ Bitmap image = new Bitmap(response.GetResponseStream());
Bitmap image = new Bitmap(response.GetResponseStream()); Size newsize;
Size newsize;
// TODO: make this a bit less hard coded
// TODO: make this a bit less hard coded if ((image.Height < 64) && (image.Width < 64))
if ((image.Height < 64) && (image.Width < 64)) {
{ newsize = new Size(32, 32);
newsize = new Size(32, 32); }
} else if ((image.Height < 128) && (image.Width < 128))
else if ((image.Height < 128) && (image.Width < 128)) {
{ newsize = new Size(64, 64);
newsize = new Size(64, 64); }
} else if ((image.Height <256) && (image.Width < 256))
else if ((image.Height <256) && (image.Width < 256)) {
{ newsize = new Size(128, 128);
newsize = new Size(128, 128); }
} else if ((image.Height < 512 && image.Width < 512))
else if ((image.Height < 512 && image.Width < 512)) {
{ newsize = new Size(256, 256);
newsize = new Size(256, 256); }
} else if ((image.Height < 1024 && image.Width < 1024))
else if ((image.Height < 1024 && image.Width < 1024)) {
{ newsize = new Size(512, 512);
newsize = new Size(512, 512); }
} else
else {
{ newsize = new Size(1024,1024);
newsize = new Size(1024,1024); }
}
Bitmap resize = new Bitmap(image, newsize);
Bitmap resize = new Bitmap(image, newsize); byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
m_textureManager.ReturnData(state.RequestID, imageJ2000);
m_textureManager.ReturnData(state.RequestID, imageJ2000); }
} }
}
public class RequestState
public class RequestState {
{ public HttpWebRequest Request = null;
public HttpWebRequest Request = null; public LLUUID RequestID = LLUUID.Zero;
public LLUUID RequestID = LLUUID.Zero; public int TimeOfRequest = 0;
public int TimeOfRequest = 0;
public RequestState(HttpWebRequest request, LLUUID requestID)
public RequestState(HttpWebRequest request, LLUUID requestID) {
{ Request = request;
Request = request; RequestID = requestID;
RequestID = requestID; }
} }
} }
} }
}

View File

@ -1,361 +1,361 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the * * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Net; using System.Net;
using libsecondlife; using libsecondlife;
using Nini.Config; using Nini.Config;
using OpenJPEGNet; using OpenJPEGNet;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using Image=System.Drawing.Image; using Image=System.Drawing.Image;
//using Cairo; //using Cairo;
namespace OpenSim.Region.Environment.Modules namespace OpenSim.Region.Environment.Modules.Scripting.VectorRender
{ {
public class VectorRenderModule : IRegionModule, IDynamicTextureRender public class VectorRenderModule : IRegionModule, IDynamicTextureRender
{ {
private Scene m_scene; private Scene m_scene;
private string m_name = "VectorRenderModule"; private string m_name = "VectorRenderModule";
private IDynamicTextureManager m_textureManager; private IDynamicTextureManager m_textureManager;
public VectorRenderModule() public VectorRenderModule()
{ {
} }
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
if (m_scene == null) if (m_scene == null)
{ {
m_scene = scene; m_scene = scene;
} }
} }
public void PostInitialise() public void PostInitialise()
{ {
m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>(); m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
if (m_textureManager != null) if (m_textureManager != null)
{ {
m_textureManager.RegisterRender(GetContentType(), this); m_textureManager.RegisterRender(GetContentType(), this);
} }
} }
public void Close() public void Close()
{ {
} }
public string Name public string Name
{ {
get { return m_name; } get { return m_name; }
} }
public bool IsSharedModule public bool IsSharedModule
{ {
get { return true; } get { return true; }
} }
private void Draw(string data, LLUUID id, string extraParams) private void Draw(string data, LLUUID id, string extraParams)
{ {
// TODO: this is a brutal hack. extraParams should actually be parsed reasonably. // TODO: this is a brutal hack. extraParams should actually be parsed reasonably.
int size = 256; int size = 256;
try { try {
size = Convert.ToInt32(extraParams); size = Convert.ToInt32(extraParams);
} catch (Exception e) { } catch (Exception e) {
//Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used //Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used
Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString()); Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString());
} }
if ((size < 128) || (size > 1024)) if ((size < 128) || (size > 1024))
size = 256; size = 256;
Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb); Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb);
Graphics graph = Graphics.FromImage(bitmap); Graphics graph = Graphics.FromImage(bitmap);
extraParams = extraParams.ToLower(); extraParams = extraParams.ToLower();
int alpha = 255; int alpha = 255;
if (extraParams == "setalpha") if (extraParams == "setalpha")
{ {
alpha = 0; alpha = 0;
} }
else else
{ {
graph.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size); graph.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size);
} }
for (int w = 0; w < bitmap.Width; w++) for (int w = 0; w < bitmap.Width; w++)
{ {
for (int h = 0; h < bitmap.Height; h++) for (int h = 0; h < bitmap.Height; h++)
{ {
bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
} }
} }
GDIDraw(data, graph); GDIDraw(data, graph);
byte[] imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); byte[] imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true);
m_textureManager.ReturnData(id, imageJ2000); m_textureManager.ReturnData(id, imageJ2000);
} }
/* /*
private void CairoDraw(string data, System.Drawing.Graphics graph) private void CairoDraw(string data, System.Drawing.Graphics graph)
{ {
using (Win32Surface draw = new Win32Surface(graph.GetHdc())) using (Win32Surface draw = new Win32Surface(graph.GetHdc()))
{ {
Context contex = new Context(draw); Context contex = new Context(draw);
contex.Antialias = Antialias.None; //fastest method but low quality contex.Antialias = Antialias.None; //fastest method but low quality
contex.LineWidth = 7; contex.LineWidth = 7;
char[] lineDelimiter = { ';' }; char[] lineDelimiter = { ';' };
char[] partsDelimiter = { ',' }; char[] partsDelimiter = { ',' };
string[] lines = data.Split(lineDelimiter); string[] lines = data.Split(lineDelimiter);
foreach (string line in lines) foreach (string line in lines)
{ {
string nextLine = line.Trim(); string nextLine = line.Trim();
if (nextLine.StartsWith("MoveTO")) if (nextLine.StartsWith("MoveTO"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, ref x, ref y); GetParams(partsDelimiter, ref nextLine, ref x, ref y);
contex.MoveTo(x, y); contex.MoveTo(x, y);
} }
else if (nextLine.StartsWith("LineTo")) else if (nextLine.StartsWith("LineTo"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, ref x, ref y); GetParams(partsDelimiter, ref nextLine, ref x, ref y);
contex.LineTo(x, y); contex.LineTo(x, y);
contex.Stroke(); contex.Stroke();
} }
} }
} }
graph.ReleaseHdc(); graph.ReleaseHdc();
} }
*/ */
private void GDIDraw(string data, Graphics graph) private void GDIDraw(string data, Graphics graph)
{ {
Point startPoint = new Point(0, 0); Point startPoint = new Point(0, 0);
Point endPoint = new Point(0, 0); Point endPoint = new Point(0, 0);
Pen drawPen = new Pen(Color.Black, 7); Pen drawPen = new Pen(Color.Black, 7);
Font myFont = new Font("Times New Roman", 14); Font myFont = new Font("Times New Roman", 14);
SolidBrush myBrush = new SolidBrush(Color.Black); SolidBrush myBrush = new SolidBrush(Color.Black);
char[] lineDelimiter = { ';' }; char[] lineDelimiter = { ';' };
char[] partsDelimiter = { ',' }; char[] partsDelimiter = { ',' };
string[] lines = data.Split(lineDelimiter); string[] lines = data.Split(lineDelimiter);
foreach (string line in lines) foreach (string line in lines)
{ {
string nextLine = line.Trim(); string nextLine = line.Trim();
//replace with switch, or even better, do some proper parsing //replace with switch, or even better, do some proper parsing
if (nextLine.StartsWith("MoveTo")) if (nextLine.StartsWith("MoveTo"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
startPoint.X = (int)x; startPoint.X = (int)x;
startPoint.Y = (int)y; startPoint.Y = (int)y;
} }
else if (nextLine.StartsWith("LineTo")) else if (nextLine.StartsWith("LineTo"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
endPoint.X = (int)x; endPoint.X = (int)x;
endPoint.Y = (int)y; endPoint.Y = (int)y;
graph.DrawLine(drawPen, startPoint, endPoint); graph.DrawLine(drawPen, startPoint, endPoint);
startPoint.X = endPoint.X; startPoint.X = endPoint.X;
startPoint.Y = endPoint.Y; startPoint.Y = endPoint.Y;
} }
else if (nextLine.StartsWith("Text")) else if (nextLine.StartsWith("Text"))
{ {
nextLine = nextLine.Remove(0, 4); nextLine = nextLine.Remove(0, 4);
nextLine = nextLine.Trim(); nextLine = nextLine.Trim();
graph.DrawString(nextLine, myFont, myBrush, startPoint); graph.DrawString(nextLine, myFont, myBrush, startPoint);
} }
else if (nextLine.StartsWith("Image")) else if (nextLine.StartsWith("Image"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
endPoint.X = (int)x; endPoint.X = (int)x;
endPoint.Y = (int)y; endPoint.Y = (int)y;
Image image = ImageHttpRequest(nextLine); Image image = ImageHttpRequest(nextLine);
graph.DrawImage(image, (float)startPoint.X, (float)startPoint.Y, x, y); graph.DrawImage(image, (float)startPoint.X, (float)startPoint.Y, x, y);
startPoint.X += endPoint.X; startPoint.X += endPoint.X;
startPoint.Y += endPoint.Y; startPoint.Y += endPoint.Y;
} }
else if (nextLine.StartsWith("Rectangle")) else if (nextLine.StartsWith("Rectangle"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y); GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y);
endPoint.X = (int)x; endPoint.X = (int)x;
endPoint.Y = (int)y; endPoint.Y = (int)y;
graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
startPoint.X += endPoint.X; startPoint.X += endPoint.X;
startPoint.Y += endPoint.Y; startPoint.Y += endPoint.Y;
} }
else if (nextLine.StartsWith("FillRectangle")) else if (nextLine.StartsWith("FillRectangle"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y); GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y);
endPoint.X = (int)x; endPoint.X = (int)x;
endPoint.Y = (int)y; endPoint.Y = (int)y;
graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
startPoint.X += endPoint.X; startPoint.X += endPoint.X;
startPoint.Y += endPoint.Y; startPoint.Y += endPoint.Y;
} }
else if (nextLine.StartsWith("Ellipse")) else if (nextLine.StartsWith("Ellipse"))
{ {
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y); GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y);
endPoint.X = (int)x; endPoint.X = (int)x;
endPoint.Y = (int)y; endPoint.Y = (int)y;
graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
startPoint.X += endPoint.X; startPoint.X += endPoint.X;
startPoint.Y += endPoint.Y; startPoint.Y += endPoint.Y;
} }
else if (nextLine.StartsWith("FontSize")) else if (nextLine.StartsWith("FontSize"))
{ {
nextLine = nextLine.Remove(0, 8); nextLine = nextLine.Remove(0, 8);
nextLine = nextLine.Trim(); nextLine = nextLine.Trim();
float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
myFont = new Font("Times New Roman", size); myFont = new Font("Times New Roman", size);
} }
else if (nextLine.StartsWith("PenSize")) else if (nextLine.StartsWith("PenSize"))
{ {
nextLine = nextLine.Remove(0, 8); nextLine = nextLine.Remove(0, 8);
nextLine = nextLine.Trim(); nextLine = nextLine.Trim();
float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
drawPen.Width = size; drawPen.Width = size;
} }
else if (nextLine.StartsWith("PenColour")) else if (nextLine.StartsWith("PenColour"))
{ {
nextLine = nextLine.Remove(0, 9); nextLine = nextLine.Remove(0, 9);
nextLine = nextLine.Trim(); nextLine = nextLine.Trim();
Color newColour = Color.FromName(nextLine); Color newColour = Color.FromName(nextLine);
myBrush.Color = newColour; myBrush.Color = newColour;
drawPen.Color = newColour; drawPen.Color = newColour;
} }
} }
} }
private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y)
{ {
line = line.Remove(0, startLength); line = line.Remove(0, startLength);
string[] parts = line.Split(partsDelimiter); string[] parts = line.Split(partsDelimiter);
if (parts.Length == 2) if (parts.Length == 2)
{ {
string xVal = parts[0].Trim(); string xVal = parts[0].Trim();
string yVal = parts[1].Trim(); string yVal = parts[1].Trim();
x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
} }
else if (parts.Length > 2) else if (parts.Length > 2)
{ {
string xVal = parts[0].Trim(); string xVal = parts[0].Trim();
string yVal = parts[1].Trim(); string yVal = parts[1].Trim();
x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
line = ""; line = "";
for (int i = 2; i < parts.Length; i++) for (int i = 2; i < parts.Length; i++)
{ {
line = line + parts[i].Trim(); line = line + parts[i].Trim();
line = line + " "; line = line + " ";
} }
} }
} }
private Bitmap ImageHttpRequest(string url) private Bitmap ImageHttpRequest(string url)
{ {
WebRequest request = HttpWebRequest.Create(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: Comment out for now as 'str' is unused. Bring it back into play later when it is used.
//Ckrinke Stream str = null; //Ckrinke Stream str = null;
HttpWebResponse response = (HttpWebResponse)(request).GetResponse(); HttpWebResponse response = (HttpWebResponse)(request).GetResponse();
if (response.StatusCode == HttpStatusCode.OK) if (response.StatusCode == HttpStatusCode.OK)
{ {
Bitmap image = new Bitmap(response.GetResponseStream()); Bitmap image = new Bitmap(response.GetResponseStream());
return image; return image;
} }
return null; return null;
} }
public string GetContentType() public string GetContentType()
{ {
return ("vector"); return ("vector");
} }
public string GetName() public string GetName()
{ {
return m_name; return m_name;
} }
public bool SupportsAsynchronous() public bool SupportsAsynchronous()
{ {
return true; return true;
} }
public byte[] ConvertUrl(string url, string extraParams) public byte[] ConvertUrl(string url, string extraParams)
{ {
return null; return null;
} }
public byte[] ConvertStream(Stream data, string extraParams) public byte[] ConvertStream(Stream data, string extraParams)
{ {
return null; return null;
} }
public bool AsyncConvertUrl(LLUUID id, string url, string extraParams) public bool AsyncConvertUrl(LLUUID id, string url, string extraParams)
{ {
return false; return false;
} }
public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams)
{ {
Draw(bodyData, id, extraParams); Draw(bodyData, id, extraParams);
return true; return true;
} }
} }
} }

View File

@ -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<ScenePresence> 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);
// }
}
}

View File

@ -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
{
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -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
}
}

View File

@ -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
{
/// <summary>
/// A generic windows bitmap loader.
/// Should be capable of handling 24-bit RGB images.
///
/// Uses the System.Drawing filesystem loader.
/// </summary>
internal class BMP : GenericSystemDrawing
{
/// <summary>
/// Exports a file to a image on the disk using a System.Drawing exporter.
/// </summary>
/// <param name="filename">The target filename</param>
/// <param name="map">The terrain channel being saved</param>
public override void SaveFile(string filename, ITerrainChannel map)
{
Bitmap colours = CreateGrayscaleBitmapFromMap(map);
colours.Save(filename, ImageFormat.Bmp);
}
/// <summary>
/// The human readable version of the file format(s) this loader handles
/// </summary>
/// <returns></returns>
public override string ToString()
{
return "BMP";
}
}
}

View File

@ -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";
}
}
}

View File

@ -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
{
/// <summary>
/// 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.
/// </summary>
public class GenericSystemDrawing : ITerrainLoader
{
#region ITerrainLoader Members
public string FileExtension
{
get { return ".gsd"; }
}
/// <summary>
/// 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
/// </summary>
/// <param name="filename">The target image to load</param>
/// <returns>A terrain channel generated from the image.</returns>
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();
}
/// <summary>
/// Exports a file to a image on the disk using a System.Drawing exporter.
/// </summary>
/// <param name="filename">The target filename</param>
/// <param name="map">The terrain channel being saved</param>
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";
}
/// <summary>
/// Protected method, generates a grayscale bitmap
/// image from a specified terrain channel.
/// </summary>
/// <param name="map">The terrain channel to export to bitmap</param>
/// <returns>A System.Drawing.Bitmap containing a grayscale image</returns>
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;
}
/// <summary>
/// Protected method, generates a coloured bitmap
/// image from a specified terrain channel.
/// </summary>
/// <param name="map">The terrain channel to export to bitmap</param>
/// <returns>A System.Drawing.Bitmap containing a coloured image</returns>
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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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";
}
}
}

View File

@ -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";
}
}
}

View File

@ -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";
}
}
}

View File

@ -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";
}
}
}

View File

@ -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
{
/// <summary>
/// Terragen File Format Loader
/// Built from specification at
/// http://www.planetside.co.uk/terragen/dev/tgterrain.html
/// </summary>
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";
}
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -1,8 +0,0 @@
namespace OpenSim.Region.Environment.Modules.Terrain
{
public interface ITerrainModule
{
void LoadFromFile(string filename);
void SaveToFile(string filename);
}
}

View File

@ -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);
}
}

View File

@ -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<IMapImageGenerator>(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;
}
}
}
}

View File

@ -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
{
/// <summary>
/// Hydraulic Erosion Brush
/// </summary>
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
}
}

View File

@ -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;
}
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
{
/// <summary>
/// Speed-Optimised Hybrid Erosion Brush
///
/// As per Jacob Olsen's Paper
/// http://www.oddlabs.com/download/terrain_generation.pdf
/// </summary>
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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
{
/// <summary>
/// Thermal Weathering Paint Brush
/// </summary>
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
}
}

View File

@ -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
{
/// <summary>
/// A new version of the old Channel class, simplified
/// </summary>
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;
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -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
/// <summary>
/// A standard set of terrain brushes and effects recognised by viewers
/// </summary>
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<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
private ITerrainChannel m_channel;
private Dictionary<string, ITerrainEffect> 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
/// <summary>
/// Creates and initialises a terrain module for a region
/// </summary>
/// <param name="scene">Region initialising</param>
/// <param name="config">Config for the region</param>
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<ITerrainModule>(this);
m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
}
/// <summary>
/// Enables terrain module when called
/// </summary>
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
/// <summary>
/// Loads a terrain file from disk and installs it in the scene.
/// </summary>
/// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
public void LoadFromFile(string filename)
{
foreach (KeyValuePair<string, ITerrainLoader> 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));
}
/// <summary>
/// Saves the current heightmap to a specified file.
/// </summary>
/// <param name="filename">The destination filename</param>
public void SaveToFile(string filename)
{
try
{
foreach (KeyValuePair<string, ITerrainLoader> 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<string, ITerrainEffect>();
// 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
/// <summary>
/// Installs into terrain module the standard suite of brushes
/// </summary>
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"];
}
/// <summary>
/// Saves the current state of the region into the revert map buffer.
/// </summary>
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];
}
}
}
/// <summary>
/// Loads a tile from a larger terrain file and installs it into the region.
/// </summary>
/// <param name="filename">The terrain file to load</param>
/// <param name="fileWidth">The width of the file in units</param>
/// <param name="fileHeight">The height of the file in units</param>
/// <param name="fileStartX">Where to begin our slice</param>
/// <param name="fileStartY">Where to begin our slice</param>
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<string, ITerrainLoader> 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;
}
}
}
}
/// <summary>
/// Performs updates to the region periodically, synchronising physics and other heightmap aware sections
/// </summary>
private void EventManager_OnTerrainTick()
{
if (m_tainted)
{
m_tainted = false;
m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised());
m_scene.SaveTerrain();
m_scene.CreateTerrainTexture(true);
}
}
/// <summary>
/// Processes commandline input. Do not call directly.
/// </summary>
/// <param name="args">Commandline arguments</param>
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);
}
}
/// <summary>
/// Installs terrain brush hook to IClientAPI
/// </summary>
/// <param name="client"></param>
private void EventManager_OnNewClient(IClientAPI client)
{
client.OnModifyTerrain += client_OnModifyTerrain;
}
/// <summary>
/// Checks to see if the terrain has been modified since last check
/// </summary>
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;
}
}
/// <summary>
/// Sends a copy of the current terrain to the scenes clients
/// </summary>
/// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
/// <param name="x">The patch corner to send</param>
/// <param name="y">The patch corner to send</param>
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<string, ITerrainEffect> 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<string, ITerrainLoader> 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
}
}

View File

@ -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;
}
}
}

View File

@ -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
{
/// <summary>
/// Version 2.0 - Very hacky compared to the original. Will fix original and release as 0.3 later.
/// </summary>
public class TreePopulatorModule : IRegionModule
{
private Scene m_scene;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private List<LLUUID> 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<LLUUID>();
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; }
}
}
}