* Rex merge, region modules.
parent
3dfb31a49c
commit
db76041e4e
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
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 AgentAssetTransactionModule : IRegionModule, IAgentAssetTransactions
|
||||
{
|
||||
private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
|
||||
private Scene m_scene = null;
|
||||
private bool m_dumpAssetsToFile = false;
|
||||
|
||||
private AgentAssetTransactionsManager m_transactionManager;
|
||||
|
||||
public AgentAssetTransactionModule()
|
||||
{
|
||||
// System.Console.WriteLine("creating AgentAssetTransactionModule");
|
||||
}
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
|
||||
{
|
||||
// System.Console.WriteLine("initialising AgentAssetTransactionModule");
|
||||
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
|
||||
scene.RegisterModuleInterface<IAgentAssetTransactions>(this);
|
||||
|
||||
scene.EventManager.OnNewClient += NewClient;
|
||||
}
|
||||
|
||||
if (m_scene == null)
|
||||
{
|
||||
m_scene = scene;
|
||||
if (config.Configs["StandAlone"] != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false);
|
||||
m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_transactionManager = new AgentAssetTransactionsManager(m_scene, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "AgentTransactionModule"; }
|
||||
}
|
||||
|
||||
public bool IsSharedModule
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void NewClient(IClientAPI client)
|
||||
{
|
||||
client.OnAssetUploadRequest += m_transactionManager.HandleUDPUploadRequest;
|
||||
client.OnXferReceive += m_transactionManager.HandleXfer;
|
||||
}
|
||||
|
||||
public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
|
||||
uint callbackID, string description, string name, sbyte invType,
|
||||
sbyte type, byte wearableType, uint nextOwnerMask)
|
||||
{
|
||||
m_transactionManager.HandleItemCreationFromTransaction(remoteClient, transactionID, folderID, callbackID, description, name, invType, type, wearableType, nextOwnerMask);
|
||||
}
|
||||
|
||||
public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
|
||||
InventoryItemBase item)
|
||||
{
|
||||
m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
|
||||
}
|
||||
|
||||
public void RemoveAgentAssetTransactions(LLUUID userID)
|
||||
{
|
||||
m_transactionManager.RemoveAgentAssetTransactions(userID);
|
||||
}
|
||||
}
|
||||
|
||||
//should merge this classes and clean up
|
||||
public class AgentAssetTransactionsManager
|
||||
{
|
||||
private static readonly log4net.ILog m_log
|
||||
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
// Fields
|
||||
public Scene MyScene;
|
||||
|
||||
/// <summary>
|
||||
/// Each agent has its own singleton collection of transactions
|
||||
/// </summary>
|
||||
private Dictionary<LLUUID, AgentAssetTransactions> AgentTransactions =
|
||||
new Dictionary<LLUUID, AgentAssetTransactions>();
|
||||
|
||||
/// <summary>
|
||||
/// Should we dump uploaded assets to the filesystem?
|
||||
/// </summary>
|
||||
private bool m_dumpAssetsToFile;
|
||||
|
||||
public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile)
|
||||
{
|
||||
MyScene = scene;
|
||||
m_dumpAssetsToFile = dumpAssetsToFile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the collection of asset transactions for the given user. If one does not already exist, it
|
||||
/// is created.
|
||||
/// </summary>
|
||||
/// <param name="userID"></param>
|
||||
/// <returns></returns>
|
||||
private AgentAssetTransactions GetUserTransactions(LLUUID userID)
|
||||
{
|
||||
lock (AgentTransactions)
|
||||
{
|
||||
if (!AgentTransactions.ContainsKey(userID))
|
||||
{
|
||||
AgentAssetTransactions transactions
|
||||
= new AgentAssetTransactions(userID, this, m_dumpAssetsToFile);
|
||||
AgentTransactions.Add(userID, transactions);
|
||||
}
|
||||
|
||||
return AgentTransactions[userID];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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).
|
||||
/// </summary>
|
||||
/// <param name="userID"></param>
|
||||
public void RemoveAgentAssetTransactions(LLUUID userID)
|
||||
{
|
||||
// m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID);
|
||||
|
||||
lock (AgentTransactions)
|
||||
{
|
||||
AgentTransactions.Remove(userID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an inventory item from data that has been received through a transaction.
|
||||
///
|
||||
/// This is called when new clothing or body parts are created. It may also be called in other
|
||||
/// situations.
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="transactionID"></param>
|
||||
/// <param name="folderID"></param>
|
||||
/// <param name="callbackID"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="invType"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="wearableType"></param>
|
||||
/// <param name="nextOwnerMask"></param>
|
||||
public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
|
||||
uint callbackID, string description, string name, sbyte invType,
|
||||
sbyte type, byte wearableType, uint nextOwnerMask)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name);
|
||||
|
||||
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
|
||||
|
||||
transactions.RequestCreateInventoryItem(
|
||||
remoteClient, transactionID, folderID, callbackID, description,
|
||||
name, invType, type, wearableType, nextOwnerMask);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update an inventory item with data that has been received through a transaction.
|
||||
///
|
||||
/// This is called when clothing or body parts are updated (for instance, with new textures or
|
||||
/// colours). It may also be called in other situations.
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="transactionID"></param>
|
||||
/// <param name="item"></param>
|
||||
public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID,
|
||||
InventoryItemBase item)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}",
|
||||
item.inventoryName);
|
||||
|
||||
AgentAssetTransactions transactions
|
||||
= GetUserTransactions(remoteClient.AgentId);
|
||||
|
||||
transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request that a client (agent) begin an asset transfer.
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="assetID"></param>
|
||||
/// <param name="transaction"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="data"></param></param>
|
||||
/// <param name="tempFile"></param>
|
||||
public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type,
|
||||
byte[] data, bool storeLocal, bool tempFile)
|
||||
{
|
||||
// Console.WriteLine("asset upload of " + assetID);
|
||||
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
|
||||
|
||||
AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
|
||||
if (uploader != null)
|
||||
{
|
||||
|
||||
if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle asset transfer data packets received in response to the asset upload request in
|
||||
/// HandleUDPUploadRequest()
|
||||
/// </summary>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <param name="xferID"></param>
|
||||
/// <param name="packetID"></param>
|
||||
/// <param name="data"></param>
|
||||
public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
|
||||
{
|
||||
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
|
||||
|
||||
transactions.HandleXfer(xferID, packetID, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE 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 System.IO;
|
||||
using libsecondlife;
|
||||
using libsecondlife.Packets;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Communications.Cache;
|
||||
|
||||
namespace OpenSim.Region.Environment.Modules
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Manage asset transactions for a single agent.
|
||||
/// </summary>
|
||||
public class AgentAssetTransactions
|
||||
{
|
||||
//private static readonly log4net.ILog m_log
|
||||
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
// Fields
|
||||
public LLUUID UserID;
|
||||
public Dictionary<LLUUID, AssetXferUploader> XferUploaders = new Dictionary<LLUUID, AssetXferUploader>();
|
||||
public AgentAssetTransactionsManager Manager;
|
||||
private bool m_dumpAssetsToFile;
|
||||
|
||||
// Methods
|
||||
public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile)
|
||||
{
|
||||
UserID = agentID;
|
||||
Manager = manager;
|
||||
m_dumpAssetsToFile = dumpAssetsToFile;
|
||||
}
|
||||
|
||||
public AssetXferUploader RequestXferUploader(LLUUID transactionID)
|
||||
{
|
||||
if (!XferUploaders.ContainsKey(transactionID))
|
||||
{
|
||||
AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile);
|
||||
|
||||
lock (XferUploaders)
|
||||
{
|
||||
XferUploaders.Add(transactionID, uploader);
|
||||
}
|
||||
|
||||
return uploader;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void HandleXfer(ulong xferID, uint packetID, byte[] data)
|
||||
{
|
||||
// AssetXferUploader uploaderFound = null;
|
||||
|
||||
lock (XferUploaders)
|
||||
{
|
||||
foreach (AssetXferUploader uploader in XferUploaders.Values)
|
||||
{
|
||||
if (uploader.XferID == xferID)
|
||||
{
|
||||
uploader.HandleXferPacket(xferID, packetID, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
|
||||
uint callbackID, string description, string name, sbyte invType,
|
||||
sbyte type, byte wearableType, uint nextOwnerMask)
|
||||
{
|
||||
if (XferUploaders.ContainsKey(transactionID))
|
||||
{
|
||||
XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID,
|
||||
callbackID, description, name, invType, type,
|
||||
wearableType, nextOwnerMask);
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
|
||||
InventoryItemBase item)
|
||||
{
|
||||
if (XferUploaders.ContainsKey(transactionID))
|
||||
{
|
||||
XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed.
|
||||
/// </summary>
|
||||
/// <param name="transactionID"></param>
|
||||
/// <returns>The asset if the upload has completed, null if it has not.</returns>
|
||||
public AssetBase GetTransactionAsset(LLUUID transactionID)
|
||||
{
|
||||
if (XferUploaders.ContainsKey(transactionID))
|
||||
{
|
||||
AssetXferUploader uploader = XferUploaders[transactionID];
|
||||
AssetBase asset = uploader.GetAssetData();
|
||||
|
||||
lock (XferUploaders)
|
||||
{
|
||||
XferUploaders.Remove(transactionID);
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Nested Types
|
||||
public class AssetXferUploader
|
||||
{
|
||||
// Fields
|
||||
public bool AddToInventory;
|
||||
public AssetBase Asset;
|
||||
public LLUUID InventFolder = LLUUID.Zero;
|
||||
private IClientAPI ourClient;
|
||||
public LLUUID TransactionID = LLUUID.Zero;
|
||||
public bool UploadComplete;
|
||||
public ulong XferID;
|
||||
private string m_name = String.Empty;
|
||||
private string m_description = String.Empty;
|
||||
private sbyte type = 0;
|
||||
private sbyte invType = 0;
|
||||
private uint nextPerm = 0;
|
||||
private bool m_finished = false;
|
||||
private bool m_createItem = false;
|
||||
private AgentAssetTransactions m_userTransactions;
|
||||
private bool m_storeLocal;
|
||||
private bool m_dumpAssetToFile;
|
||||
|
||||
public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile)
|
||||
{
|
||||
m_userTransactions = transactions;
|
||||
m_dumpAssetToFile = dumpAssetToFile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process transfer data received from the client.
|
||||
/// </summary>
|
||||
/// <param name="xferID"></param>
|
||||
/// <param name="packetID"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <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)
|
||||
{
|
||||
if (XferID == xferID)
|
||||
{
|
||||
if (Asset.Data.Length > 1)
|
||||
{
|
||||
byte[] destinationArray = new byte[Asset.Data.Length + data.Length];
|
||||
Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length);
|
||||
Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length);
|
||||
Asset.Data = destinationArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] buffer2 = new byte[data.Length - 4];
|
||||
Array.Copy(data, 4, buffer2, 0, data.Length - 4);
|
||||
Asset.Data = buffer2;
|
||||
}
|
||||
ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
|
||||
newPack.XferID.ID = xferID;
|
||||
newPack.XferID.Packet = packetID;
|
||||
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
|
||||
if ((packetID & 0x80000000) != 0)
|
||||
{
|
||||
SendCompleteMessage();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialise asset transfer from the client
|
||||
/// </summary>
|
||||
/// <param name="xferID"></param>
|
||||
/// <param name="packetID"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns>True if the transfer is complete, false otherwise</returns>
|
||||
public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data,
|
||||
bool storeLocal, bool tempFile)
|
||||
{
|
||||
ourClient = remoteClient;
|
||||
Asset = new AssetBase();
|
||||
Asset.FullID = assetID;
|
||||
Asset.InvType = type;
|
||||
Asset.Type = type;
|
||||
Asset.Data = data;
|
||||
Asset.Name = "blank";
|
||||
Asset.Description = "empty";
|
||||
Asset.Local = storeLocal;
|
||||
Asset.Temporary = tempFile;
|
||||
|
||||
TransactionID = transaction;
|
||||
m_storeLocal = storeLocal;
|
||||
if (Asset.Data.Length > 2)
|
||||
{
|
||||
SendCompleteMessage();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RequestStartXfer();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void RequestStartXfer()
|
||||
{
|
||||
UploadComplete = false;
|
||||
XferID = Util.GetNextXferID();
|
||||
RequestXferPacket newPack = new RequestXferPacket();
|
||||
newPack.XferID.ID = XferID;
|
||||
newPack.XferID.VFileType = Asset.Type;
|
||||
newPack.XferID.VFileID = Asset.FullID;
|
||||
newPack.XferID.FilePath = 0;
|
||||
newPack.XferID.Filename = new byte[0];
|
||||
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
|
||||
}
|
||||
|
||||
protected void SendCompleteMessage()
|
||||
{
|
||||
UploadComplete = true;
|
||||
AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
|
||||
newPack.AssetBlock.Type = Asset.Type;
|
||||
newPack.AssetBlock.Success = true;
|
||||
newPack.AssetBlock.UUID = Asset.FullID;
|
||||
ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset);
|
||||
m_finished = true;
|
||||
if (m_createItem)
|
||||
{
|
||||
DoCreateItem();
|
||||
}
|
||||
else if (m_storeLocal)
|
||||
{
|
||||
m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
|
||||
}
|
||||
|
||||
// Console.WriteLine("upload complete "+ this.TransactionID);
|
||||
|
||||
if (m_dumpAssetToFile)
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
string filename =
|
||||
String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day,
|
||||
now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type);
|
||||
SaveAssetToFile(filename, Asset.Data);
|
||||
}
|
||||
}
|
||||
|
||||
///Left this in and commented in case there are unforseen issues
|
||||
//private void SaveAssetToFile(string filename, byte[] data)
|
||||
//{
|
||||
// FileStream fs = File.Create(filename);
|
||||
// BinaryWriter bw = new BinaryWriter(fs);
|
||||
// bw.Write(data);
|
||||
// bw.Close();
|
||||
// fs.Close();
|
||||
//}
|
||||
private void SaveAssetToFile(string filename, byte[] data)
|
||||
{
|
||||
string assetPath = "UserAssets";
|
||||
if (!Directory.Exists(assetPath))
|
||||
{
|
||||
Directory.CreateDirectory(assetPath);
|
||||
}
|
||||
FileStream fs = File.Create(Path.Combine(assetPath, filename));
|
||||
BinaryWriter bw = new BinaryWriter(fs);
|
||||
bw.Write(data);
|
||||
bw.Close();
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID,
|
||||
uint callbackID, string description, string name, sbyte invType,
|
||||
sbyte type, byte wearableType, uint nextOwnerMask)
|
||||
{
|
||||
if (TransactionID == transactionID)
|
||||
{
|
||||
InventFolder = folderID;
|
||||
m_name = name;
|
||||
m_description = description;
|
||||
this.type = type;
|
||||
this.invType = invType;
|
||||
nextPerm = nextOwnerMask;
|
||||
Asset.Name = name;
|
||||
Asset.Description = description;
|
||||
Asset.Type = type;
|
||||
Asset.InvType = invType;
|
||||
m_createItem = true;
|
||||
if (m_finished)
|
||||
{
|
||||
DoCreateItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID,
|
||||
InventoryItemBase item)
|
||||
{
|
||||
if (TransactionID == transactionID)
|
||||
{
|
||||
CachedUserInfo userInfo =
|
||||
m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(
|
||||
remoteClient.AgentId);
|
||||
|
||||
if (userInfo != null)
|
||||
{
|
||||
LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId);
|
||||
|
||||
AssetBase asset
|
||||
= m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset(
|
||||
assetID, (item.assetType == (int) AssetType.Texture ? true : false));
|
||||
|
||||
if (asset == null)
|
||||
{
|
||||
asset = m_userTransactions.GetTransactionAsset(transactionID);
|
||||
}
|
||||
|
||||
if (asset != null && asset.FullID == assetID)
|
||||
{
|
||||
asset.Name = item.inventoryName;
|
||||
asset.Description = item.inventoryDescription;
|
||||
asset.InvType = (sbyte) item.invType;
|
||||
asset.Type = (sbyte) item.assetType;
|
||||
item.assetID = asset.FullID;
|
||||
|
||||
m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
|
||||
}
|
||||
|
||||
userInfo.UpdateItem(remoteClient.AgentId, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DoCreateItem()
|
||||
{
|
||||
//really need to fix this call, if lbsa71 saw this he would die.
|
||||
m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset);
|
||||
CachedUserInfo userInfo =
|
||||
m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId);
|
||||
if (userInfo != null)
|
||||
{
|
||||
InventoryItemBase item = new InventoryItemBase();
|
||||
item.avatarID = ourClient.AgentId;
|
||||
item.creatorsID = ourClient.AgentId;
|
||||
item.inventoryID = LLUUID.Random();
|
||||
item.assetID = Asset.FullID;
|
||||
item.inventoryDescription = m_description;
|
||||
item.inventoryName = m_name;
|
||||
item.assetType = type;
|
||||
item.invType = invType;
|
||||
item.parentFolderID = InventFolder;
|
||||
item.inventoryBasePermissions = 2147483647;
|
||||
item.inventoryCurrentPermissions = 2147483647;
|
||||
item.inventoryNextPermissions = nextPerm;
|
||||
|
||||
userInfo.AddItem(ourClient.AgentId, item);
|
||||
ourClient.SendInventoryItemCreateUpdate(item);
|
||||
}
|
||||
}
|
||||
|
||||
public AssetBase GetAssetData()
|
||||
{
|
||||
if (m_finished)
|
||||
{
|
||||
return Asset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenSim.Region.Environment.Scenes;
|
||||
using OpenSim.Framework;
|
||||
using TribalMedia.Framework.Data;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using libsecondlife;
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
|
@ -35,37 +36,174 @@ using OpenSim.Framework.Communications.Cache;
|
|||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Region.Environment.Interfaces;
|
||||
using OpenSim.Region.Environment.Scenes;
|
||||
using OpenSim.Framework.Data;
|
||||
using TribalMedia.Framework.Data;
|
||||
|
||||
namespace OpenSim.Region.Environment.Modules
|
||||
{
|
||||
public class AvatarFactoryModule : IAvatarFactory
|
||||
{
|
||||
private Scene m_scene = null;
|
||||
private 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 string m_connectionString;
|
||||
private bool m_configured = false;
|
||||
private BaseDatabaseConnector m_databaseMapper;
|
||||
private AppearanceTableMapper m_appearanceMapper;
|
||||
|
||||
private Dictionary<LLUUID, EventWaitHandle> m_fetchesInProgress = new Dictionary<LLUUID, EventWaitHandle>();
|
||||
private object m_syncLock = new object();
|
||||
|
||||
public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
|
||||
{
|
||||
if (m_avatarsAppearance.ContainsKey(avatarId))
|
||||
|
||||
//should only let one thread at a time do this part
|
||||
EventWaitHandle waitHandle = null;
|
||||
bool fetchInProgress = false;
|
||||
lock (m_syncLock)
|
||||
{
|
||||
appearance = m_avatarsAppearance[avatarId];
|
||||
appearance = CheckCache(avatarId);
|
||||
if (appearance != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//not in cache so check to see if another thread is already fetching it
|
||||
if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle))
|
||||
{
|
||||
fetchInProgress = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fetchInProgress = false;
|
||||
|
||||
//no thread already fetching this appearance, so add a wait handle to list
|
||||
//for any following threads that want the same appearance
|
||||
waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
|
||||
m_fetchesInProgress.Add(avatarId, waitHandle);
|
||||
}
|
||||
}
|
||||
|
||||
if (fetchInProgress)
|
||||
{
|
||||
waitHandle.WaitOne();
|
||||
appearance = CheckCache(avatarId);
|
||||
if (appearance != null)
|
||||
{
|
||||
waitHandle = null;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
waitHandle = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(5000);
|
||||
|
||||
//this is the first thread to request this appearance
|
||||
//so let it check the db and if not found then create a default appearance
|
||||
//and add that to the cache
|
||||
appearance = CheckDatabase(avatarId);
|
||||
if (appearance != null)
|
||||
{
|
||||
//appearance has now been added to cache so lets pulse any waiting threads
|
||||
lock (m_syncLock)
|
||||
{
|
||||
m_fetchesInProgress.Remove(avatarId);
|
||||
waitHandle.Set();
|
||||
}
|
||||
// waitHandle.Close();
|
||||
waitHandle = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
//not found a appearance for the user, so create a new default one
|
||||
appearance = CreateDefault(avatarId);
|
||||
if (appearance != null)
|
||||
{
|
||||
//update database
|
||||
if (m_enablePersist)
|
||||
{
|
||||
m_appearanceMapper.Add(avatarId.UUID, appearance);
|
||||
}
|
||||
|
||||
//add appearance to dictionary cache
|
||||
lock (m_avatarsAppearance)
|
||||
{
|
||||
m_avatarsAppearance[avatarId] = appearance;
|
||||
}
|
||||
|
||||
//appearance has now been added to cache so lets pulse any waiting threads
|
||||
lock (m_syncLock)
|
||||
{
|
||||
m_fetchesInProgress.Remove(avatarId);
|
||||
waitHandle.Set();
|
||||
}
|
||||
// waitHandle.Close();
|
||||
waitHandle = null;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//something went wrong, so release the wait handle and remove it
|
||||
//all waiting threads will fail to find cached appearance
|
||||
//but its better for them to fail than wait for ever
|
||||
lock (m_syncLock)
|
||||
{
|
||||
m_fetchesInProgress.Remove(avatarId);
|
||||
waitHandle.Set();
|
||||
}
|
||||
//waitHandle.Close();
|
||||
waitHandle = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AvatarAppearance CreateDefault(LLUUID avatarId)
|
||||
{
|
||||
AvatarAppearance appearance = null;
|
||||
AvatarWearable[] wearables;
|
||||
byte[] visualParams;
|
||||
GetDefaultAvatarAppearance(out wearables, out visualParams);
|
||||
appearance = new AvatarAppearance(avatarId, wearables, visualParams);
|
||||
try
|
||||
|
||||
return appearance;
|
||||
}
|
||||
|
||||
private AvatarAppearance CheckDatabase(LLUUID avatarId)
|
||||
{
|
||||
AvatarAppearance appearance = null;
|
||||
if (m_enablePersist)
|
||||
{
|
||||
if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance))
|
||||
{
|
||||
appearance.VisualParams = GetDefaultVisualParams();
|
||||
appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry();
|
||||
lock (m_avatarsAppearance)
|
||||
{
|
||||
m_avatarsAppearance[avatarId] = appearance;
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
}
|
||||
}
|
||||
return appearance;
|
||||
}
|
||||
|
||||
private AvatarAppearance CheckCache(LLUUID avatarId)
|
||||
{
|
||||
MainLog.Instance.Error("AVATAR", "Unable to load appearance for uninitialized avatar");
|
||||
AvatarAppearance appearance = null;
|
||||
lock (m_avatarsAppearance)
|
||||
{
|
||||
if (m_avatarsAppearance.ContainsKey(avatarId))
|
||||
{
|
||||
appearance = m_avatarsAppearance[avatarId];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return appearance;
|
||||
}
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource source)
|
||||
|
@ -77,6 +215,24 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
m_scene = scene;
|
||||
}
|
||||
|
||||
if (!m_configured)
|
||||
{
|
||||
m_configured = true;
|
||||
try
|
||||
{
|
||||
m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false);
|
||||
m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", "");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
if (m_enablePersist)
|
||||
{
|
||||
m_databaseMapper = new MySQLDatabaseMapper(m_connectionString);
|
||||
m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
|
@ -109,17 +265,32 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
|
||||
{
|
||||
IClientAPI clientView = (IClientAPI) sender;
|
||||
IClientAPI clientView = (IClientAPI)sender;
|
||||
CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
|
||||
if (profile != null)
|
||||
{
|
||||
if (profile.RootFolder != null)
|
||||
{
|
||||
//Todo look up the assetid from the inventory cache for each itemId that is in AvatarWearingArgs
|
||||
// then store assetid and itemId and wearable type in a database
|
||||
if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
|
||||
{
|
||||
AvatarAppearance avatAppearance = null;
|
||||
lock (m_avatarsAppearance)
|
||||
{
|
||||
avatAppearance = m_avatarsAppearance[clientView.AgentId];
|
||||
}
|
||||
|
||||
foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
|
||||
{
|
||||
if (wear.Type < 13)
|
||||
{
|
||||
if (wear.ItemID == LLUUID.Zero)
|
||||
{
|
||||
avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero;
|
||||
avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero;
|
||||
|
||||
UpdateDatabase(clientView.AgentId, avatAppearance);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLUUID assetId;
|
||||
|
||||
|
@ -127,13 +298,10 @@ namespace OpenSim.Region.Environment.Modules
|
|||
if (baseItem != null)
|
||||
{
|
||||
assetId = baseItem.assetID;
|
||||
//temporary dictionary storage. This should be storing to a database
|
||||
|
||||
if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
|
||||
{
|
||||
AvatarAppearance avatAppearance = m_avatarsAppearance[clientView.AgentId];
|
||||
avatAppearance.Wearables[wear.Type].AssetID = assetId;
|
||||
avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
|
||||
|
||||
UpdateDatabase(clientView.AgentId, avatAppearance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +309,15 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance)
|
||||
{
|
||||
if (m_enablePersist)
|
||||
{
|
||||
m_appearanceMapper.Update(userID.UUID, avatAppearance);
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -87,7 +87,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
string bornOn = "Before now";
|
||||
string flAbout = "First life? What is one of those? OpenSim is my life!";
|
||||
LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000");
|
||||
remoteClient.SendAvatarProperties(avatarID, about, bornOn, "", flAbout, 0, LLUUID.Zero, LLUUID.Zero, "",
|
||||
remoteClient.SendAvatarProperties(avatarID, about, bornOn, System.String.Empty, flAbout, 0, LLUUID.Zero, LLUUID.Zero, System.String.Empty,
|
||||
partner);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
using Nini.Config;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Region.Environment.Interfaces;
|
||||
using OpenSim.Region.Environment.Scenes;
|
||||
using libsecondlife;
|
||||
using MoneyTransferArgs = OpenSim.Region.Environment.Scenes.EventManager.MoneyTransferArgs;
|
||||
|
||||
namespace OpenSim.Region.Environment.Modules
|
||||
{
|
||||
public class BetaGridLikeMoneyModule: IRegionModule
|
||||
{
|
||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Dictionary<ulong,Scene> m_scenel = new Dictionary<ulong,Scene>();
|
||||
|
||||
private IConfigSource m_gConfig;
|
||||
|
||||
private bool m_keepMoneyAcrossLogins = true;
|
||||
|
||||
private int m_minFundsBeforeRefresh = 100;
|
||||
|
||||
private int m_stipend = 1000;
|
||||
|
||||
private bool m_enabled = true;
|
||||
|
||||
|
||||
|
||||
private Dictionary<LLUUID, int> m_KnownClientFunds = new Dictionary<LLUUID, int>();
|
||||
|
||||
|
||||
|
||||
private bool gridmode = false;
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
m_gConfig = config;
|
||||
ReadConfigAndPopulate();
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
lock (m_scenel)
|
||||
{
|
||||
|
||||
if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
|
||||
{
|
||||
m_scenel[scene.RegionInfo.RegionHandle] = scene;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scenel.Add(scene.RegionInfo.RegionHandle, scene);
|
||||
}
|
||||
}
|
||||
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnMoneyTransfer += MoneyTransferAction;
|
||||
scene.EventManager.OnClientClosed += ClientClosed;
|
||||
}
|
||||
}
|
||||
private void ReadConfigAndPopulate()
|
||||
{
|
||||
IConfig startupConfig = m_gConfig.Configs["Startup"];
|
||||
gridmode = startupConfig.GetBoolean("gridmode", false);
|
||||
m_enabled = (startupConfig.GetString("moneymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule");
|
||||
|
||||
}
|
||||
|
||||
private void OnNewClient(IClientAPI client)
|
||||
{
|
||||
// Here we check if we're in grid mode
|
||||
// I imagine that the 'check balance'
|
||||
// function for the client should be here or shortly after
|
||||
|
||||
if (gridmode)
|
||||
{
|
||||
CheckExistAndRefreshFunds(client.AgentId);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckExistAndRefreshFunds(client.AgentId);
|
||||
}
|
||||
|
||||
// Subscribe to Money messages
|
||||
client.OnMoneyBalanceRequest += SendMoneyBalance;
|
||||
client.OnLogout += ClientClosed;
|
||||
|
||||
}
|
||||
|
||||
public void ClientClosed(LLUUID AgentID)
|
||||
{
|
||||
lock (m_KnownClientFunds)
|
||||
{
|
||||
if (!m_keepMoneyAcrossLogins)
|
||||
m_KnownClientFunds.Remove(AgentID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void MoneyTransferAction (Object osender, MoneyTransferArgs e)
|
||||
{
|
||||
IClientAPI sender = null;
|
||||
IClientAPI receiver = null;
|
||||
|
||||
sender = LocateClientObject(e.sender);
|
||||
if (sender != null)
|
||||
{
|
||||
|
||||
|
||||
receiver = LocateClientObject(e.reciever);
|
||||
bool transactionresult = doMoneyTranfer(e.sender, e.reciever, e.amount);
|
||||
|
||||
if (e.sender != e.reciever)
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender));
|
||||
}
|
||||
}
|
||||
|
||||
if (receiver != null)
|
||||
{
|
||||
receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.reciever));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" + e.sender.ToString() + " Reciver: " + e.reciever.ToString() + " Amount: " + e.amount.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private bool doMoneyTranfer(LLUUID Sender, LLUUID Receiver, int amount)
|
||||
{
|
||||
bool result = false;
|
||||
if (amount >= 0)
|
||||
{
|
||||
lock (m_KnownClientFunds)
|
||||
{
|
||||
// If we don't know about the sender, then the sender can't
|
||||
// actually be here and therefore this is likely fraud or outdated.
|
||||
if (m_KnownClientFunds.ContainsKey(Sender))
|
||||
{
|
||||
// Does the sender have enough funds to give?
|
||||
if (m_KnownClientFunds[Sender] >= amount)
|
||||
{
|
||||
// Subtract the funds from the senders account
|
||||
m_KnownClientFunds[Sender] -= amount;
|
||||
|
||||
// do we know about the receiver?
|
||||
if (!m_KnownClientFunds.ContainsKey(Receiver))
|
||||
{
|
||||
// Make a record for them so they get the updated balance when they login
|
||||
CheckExistAndRefreshFunds(Receiver);
|
||||
}
|
||||
|
||||
//Add the amount to the Receiver's funds
|
||||
m_KnownClientFunds[Receiver] += amount;
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// These below are redundant to make this clearer to read
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private IClientAPI LocateClientObject(LLUUID AgentID)
|
||||
{
|
||||
ScenePresence tPresence = null;
|
||||
IClientAPI rclient = null;
|
||||
|
||||
lock (m_scenel)
|
||||
{
|
||||
foreach (Scene _scene in m_scenel.Values)
|
||||
{
|
||||
tPresence = _scene.GetScenePresence(AgentID);
|
||||
if (tPresence != null)
|
||||
{
|
||||
if (!tPresence.IsChildAgent)
|
||||
{
|
||||
rclient = tPresence.ControllingClient;
|
||||
}
|
||||
}
|
||||
if (rclient != null)
|
||||
{
|
||||
return rclient;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ClientClosed(IClientAPI client)
|
||||
{
|
||||
ClientClosed(client.AgentId);
|
||||
}
|
||||
|
||||
public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID TransactionID)
|
||||
{
|
||||
if (client.AgentId == agentID && client.SessionId == SessionID)
|
||||
{
|
||||
|
||||
int returnfunds = 0;
|
||||
|
||||
try
|
||||
{
|
||||
returnfunds = GetFundsForAgentID(agentID);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
client.SendAlertMessage(e.Message + " ");
|
||||
}
|
||||
|
||||
client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.SendAlertMessage("Unable to send your money balance to you!");
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckExistAndRefreshFunds(LLUUID agentID)
|
||||
{
|
||||
lock (m_KnownClientFunds)
|
||||
{
|
||||
if (!m_KnownClientFunds.ContainsKey(agentID))
|
||||
{
|
||||
m_KnownClientFunds.Add(agentID, m_stipend);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh)
|
||||
{
|
||||
m_KnownClientFunds[agentID] = m_stipend;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private int GetFundsForAgentID(LLUUID AgentID)
|
||||
{
|
||||
int returnfunds = 0;
|
||||
lock (m_KnownClientFunds)
|
||||
{
|
||||
if (m_KnownClientFunds.ContainsKey(AgentID))
|
||||
{
|
||||
returnfunds = m_KnownClientFunds[AgentID];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unable to get funds.");
|
||||
}
|
||||
}
|
||||
return returnfunds;
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "BetaGridLikeMoneyModule"; }
|
||||
}
|
||||
|
||||
public bool IsSharedModule
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -43,8 +43,9 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
public class ChatModule : IRegionModule, ISimChat
|
||||
{
|
||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private List<Scene> m_scenes = new List<Scene>();
|
||||
private LogBase m_log;
|
||||
|
||||
private int m_whisperdistance = 10;
|
||||
private int m_saydistance = 30;
|
||||
|
@ -52,12 +53,16 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
private IRCChatModule m_irc = null;
|
||||
|
||||
public ChatModule()
|
||||
{
|
||||
m_log = MainLog.Instance;
|
||||
}
|
||||
private string m_last_new_user = null;
|
||||
private string m_last_leaving_user = null;
|
||||
private string m_defaultzone = null;
|
||||
internal object m_syncInit = new object();
|
||||
internal object m_syncLogout = new object();
|
||||
private Thread m_irc_connector=null;
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
lock (m_syncInit)
|
||||
{
|
||||
// wrap this in a try block so that defaults will work if
|
||||
// the config file doesn't specify otherwise.
|
||||
|
@ -70,6 +75,13 @@ namespace OpenSim.Region.Environment.Modules
|
|||
catch (Exception)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
m_defaultzone = config.Configs["IRC"].GetString("nick","Sim");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
if (!m_scenes.Contains(scene))
|
||||
{
|
||||
|
@ -79,14 +91,37 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
|
||||
// setup IRC Relay
|
||||
m_irc = new IRCChatModule(config);
|
||||
if (m_irc == null) { m_irc = new IRCChatModule(config); }
|
||||
if (m_irc_connector == null) {
|
||||
m_irc_connector = new Thread(IRCConnectRun);
|
||||
m_irc_connector.Name = "IRCConnectorThread";
|
||||
m_irc_connector.IsBackground = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
if (m_irc.Enabled)
|
||||
{
|
||||
m_irc.Connect(m_scenes);
|
||||
try
|
||||
{
|
||||
//m_irc.Connect(m_scenes);
|
||||
if (m_irc_connector == null) {
|
||||
m_irc_connector = new Thread(IRCConnectRun);
|
||||
m_irc_connector.Name = "IRCConnectorThread";
|
||||
m_irc_connector.IsBackground = true;
|
||||
}
|
||||
if (!m_irc_connector.IsAlive) {
|
||||
m_irc_connector.Start();
|
||||
OpenSim.Framework.ThreadTracker.Add(m_irc_connector);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,10 +141,63 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
|
||||
public void NewClient(IClientAPI client)
|
||||
{
|
||||
try
|
||||
{
|
||||
client.OnChatFromViewer += SimChat;
|
||||
|
||||
if ((m_irc.Enabled) && (m_irc.Connected))
|
||||
{
|
||||
string clientName = client.FirstName + " " + client.LastName;
|
||||
// handles simple case. May not work for hundred connecting in per second.
|
||||
// and the NewClients calles getting interleved
|
||||
// but filters out multiple reports
|
||||
if (clientName != m_last_new_user)
|
||||
{
|
||||
m_last_new_user = clientName;
|
||||
string clientRegion = FindClientRegion(client.FirstName, client.LastName);
|
||||
m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in "+clientRegion);
|
||||
}
|
||||
}
|
||||
client.OnLogout += ClientLoggedOut;
|
||||
client.OnConnectionClosed += ClientLoggedOut;
|
||||
//client.OnDisconnectUser += ClientLoggedOut;
|
||||
client.OnLogout += ClientLoggedOut;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientLoggedOut(IClientAPI client)
|
||||
{
|
||||
lock (m_syncLogout)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((m_irc.Enabled) && (m_irc.Connected))
|
||||
{
|
||||
string clientName = client.FirstName + " " + client.LastName;
|
||||
string clientRegion = FindClientRegion(client.FirstName, client.LastName);
|
||||
// handles simple case. May not work for hundred connecting in per second.
|
||||
// and the NewClients calles getting interleved
|
||||
// but filters out multiple reports
|
||||
if (clientName != m_last_leaving_user)
|
||||
{
|
||||
m_last_leaving_user = clientName;
|
||||
m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion);
|
||||
m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos,
|
||||
LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message)
|
||||
{
|
||||
|
@ -133,6 +221,8 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public void SimChat(Object sender, ChatFromViewerArgs e)
|
||||
{
|
||||
// FROM: Sim TO: IRC
|
||||
|
||||
ScenePresence avatar = null;
|
||||
|
||||
//TODO: Move ForEachScenePresence and others into IScene.
|
||||
|
@ -144,7 +234,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
// Filled in since it's easier than rewriting right now.
|
||||
LLVector3 fromPos = e.Position;
|
||||
LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX*256, scene.RegionInfo.RegionLocY*256, 0);
|
||||
LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||
|
||||
string fromName = e.From;
|
||||
string message = e.Message;
|
||||
|
@ -158,11 +248,31 @@ namespace OpenSim.Region.Environment.Modules
|
|||
if (avatar != null)
|
||||
{
|
||||
fromPos = avatar.AbsolutePosition;
|
||||
regionPos = new LLVector3(scene.RegionInfo.RegionLocX*256, scene.RegionInfo.RegionLocY*256, 0);
|
||||
regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||
fromName = avatar.Firstname + " " + avatar.Lastname;
|
||||
fromAgentID = e.Sender.AgentId;
|
||||
}
|
||||
|
||||
// Try to reconnect to server if not connected
|
||||
if ((m_irc.Enabled)&&(!m_irc.Connected))
|
||||
{
|
||||
// In a non-blocking way. Eventually the connector will get it started
|
||||
try
|
||||
{
|
||||
if (m_irc_connector == null) { m_irc_connector = new Thread(IRCConnectRun);
|
||||
m_irc_connector.Name = "IRCConnectorThread";
|
||||
m_irc_connector.IsBackground = true;
|
||||
}
|
||||
if (!m_irc_connector.IsAlive) {
|
||||
m_irc_connector.Start();
|
||||
OpenSim.Framework.ThreadTracker.Add(m_irc_connector);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Message.Length > 0)
|
||||
{
|
||||
if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC
|
||||
|
@ -183,15 +293,54 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if IRC is enabled then just keep trying using a monitor thread
|
||||
public void IRCConnectRun()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if ((m_irc.Enabled)&&(!m_irc.Connected))
|
||||
{
|
||||
m_irc.Connect(m_scenes);
|
||||
|
||||
}
|
||||
Thread.Sleep(15000);
|
||||
}
|
||||
}
|
||||
|
||||
public string FindClientRegion(string client_FirstName,string client_LastName)
|
||||
{
|
||||
string sourceRegion = null;
|
||||
foreach (Scene s in m_scenes)
|
||||
{
|
||||
s.ForEachScenePresence(delegate(ScenePresence presence)
|
||||
{
|
||||
if ((presence.IsChildAgent==false)
|
||||
&&(presence.Firstname==client_FirstName)
|
||||
&&(presence.Lastname==client_LastName))
|
||||
{
|
||||
sourceRegion = presence.Scene.RegionInfo.RegionName;
|
||||
//sourceRegion= s.RegionInfo.RegionName;
|
||||
}
|
||||
});
|
||||
if (sourceRegion != null) return sourceRegion;
|
||||
}
|
||||
if (m_defaultzone == null) { m_defaultzone = "Sim"; }
|
||||
return m_defaultzone;
|
||||
}
|
||||
}
|
||||
|
||||
internal class IRCChatModule
|
||||
{
|
||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private string m_server = null;
|
||||
private uint m_port = 6668;
|
||||
private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot";
|
||||
private string m_nick = null;
|
||||
private string m_basenick = null;
|
||||
private string m_channel = null;
|
||||
private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}";
|
||||
|
||||
private NetworkStream m_stream;
|
||||
private TcpClient m_tcp;
|
||||
|
@ -200,12 +349,13 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
private Thread pingSender;
|
||||
private Thread listener;
|
||||
internal object m_syncConnect = new object();
|
||||
|
||||
private bool m_enabled = false;
|
||||
private bool m_connected = false;
|
||||
|
||||
private List<Scene> m_scenes = null;
|
||||
private LogBase m_log;
|
||||
private List<Scene> m_last_scenes = null;
|
||||
|
||||
public IRCChatModule(IConfigSource config)
|
||||
{
|
||||
|
@ -214,43 +364,76 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_writer = null;
|
||||
m_reader = null;
|
||||
|
||||
// configuration in OpenSim.ini
|
||||
// [IRC]
|
||||
// server = chat.freenode.net
|
||||
// nick = OSimBot_mysim
|
||||
// ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot
|
||||
// ; username is the IRC command line sent
|
||||
// ; USER <irc_user> <visible=8,invisible=0> * : <IRC_realname>
|
||||
// channel = #opensim-regions
|
||||
// port = 6667
|
||||
// ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message
|
||||
// ;for <bot>:<user in region> :<message>
|
||||
// ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"
|
||||
// ;for <bot>:<message> - <user of region> :
|
||||
// ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}"
|
||||
// ;for <bot>:<message> - from <user> :
|
||||
// ;msgformat = "PRIVMSG {0} : {3} - from {1}"
|
||||
// Traps I/O disconnects so it does not crash the sim
|
||||
// Trys to reconnect if disconnected and someone says something
|
||||
// Tells IRC server "QUIT" when doing a close (just to be nice)
|
||||
// Default port back to 6667
|
||||
|
||||
try
|
||||
{
|
||||
m_server = config.Configs["IRC"].GetString("server");
|
||||
m_nick = config.Configs["IRC"].GetString("nick");
|
||||
m_basenick = m_nick;
|
||||
m_channel = config.Configs["IRC"].GetString("channel");
|
||||
m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port);
|
||||
m_user = config.Configs["IRC"].GetString("username", m_user);
|
||||
m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat);
|
||||
if (m_server != null && m_nick != null && m_channel != null)
|
||||
{
|
||||
m_nick = m_nick + Util.RandomClass.Next(1, 99);
|
||||
m_enabled = true;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
MainLog.Instance.Verbose("CHAT", "No IRC config information, skipping IRC bridge configuration");
|
||||
m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration");
|
||||
}
|
||||
m_log = MainLog.Instance;
|
||||
}
|
||||
|
||||
public bool Connect(List<Scene> scenes)
|
||||
{
|
||||
lock (m_syncConnect)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_connected) return true;
|
||||
m_scenes = scenes;
|
||||
if (m_last_scenes == null) { m_last_scenes = scenes; }
|
||||
|
||||
m_tcp = new TcpClient(m_server, (int) m_port);
|
||||
m_log.Verbose("IRC", "Connecting...");
|
||||
m_tcp = new TcpClient(m_server, (int)m_port);
|
||||
m_log.Info("[IRC]: Connecting...");
|
||||
m_stream = m_tcp.GetStream();
|
||||
m_log.Verbose("IRC", "Connected to " + m_server);
|
||||
m_log.Info("[IRC]: Connected to " + m_server);
|
||||
m_reader = new StreamReader(m_stream);
|
||||
m_writer = new StreamWriter(m_stream);
|
||||
|
||||
pingSender = new Thread(new ThreadStart(PingRun));
|
||||
pingSender.Name = "PingSenderThread";
|
||||
pingSender.IsBackground = true;
|
||||
pingSender.Start();
|
||||
OpenSim.Framework.ThreadTracker.Add(pingSender);
|
||||
|
||||
listener = new Thread(new ThreadStart(ListenerRun));
|
||||
listener.Name = "IRCChatModuleListenerThread";
|
||||
listener.IsBackground = true;
|
||||
listener.Start();
|
||||
OpenSim.Framework.ThreadTracker.Add(listener);
|
||||
|
||||
m_writer.WriteLine(m_user);
|
||||
m_writer.Flush();
|
||||
|
@ -258,7 +441,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_writer.Flush();
|
||||
m_writer.WriteLine("JOIN " + m_channel);
|
||||
m_writer.Flush();
|
||||
m_log.Verbose("IRC", "Connection fully established");
|
||||
m_log.Info("[IRC]: Connection fully established");
|
||||
m_connected = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -267,6 +450,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
return m_connected;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
|
@ -278,26 +462,60 @@ namespace OpenSim.Region.Environment.Modules
|
|||
get { return m_connected; }
|
||||
}
|
||||
|
||||
public string Nick
|
||||
{
|
||||
get { return m_nick; }
|
||||
}
|
||||
|
||||
public void Reconnect()
|
||||
{
|
||||
m_connected = false;
|
||||
listener.Abort();
|
||||
pingSender.Abort();
|
||||
m_writer.Close();
|
||||
m_reader.Close();
|
||||
m_tcp.Close();
|
||||
if (m_enabled) { Connect(m_last_scenes); }
|
||||
|
||||
}
|
||||
|
||||
public void PrivMsg(string from, string region, string msg)
|
||||
{
|
||||
// One message to the IRC server
|
||||
|
||||
try
|
||||
{
|
||||
if (m_privmsgformat == null)
|
||||
{
|
||||
m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg);
|
||||
}
|
||||
m_writer.Flush();
|
||||
m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
m_log.Error("IRC", "Disconnected from IRC server.");
|
||||
listener.Abort();
|
||||
pingSender.Abort();
|
||||
m_connected = false;
|
||||
m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)");
|
||||
Reconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> ExtractMsg(string input)
|
||||
{
|
||||
//examines IRC commands and extracts any private messages
|
||||
// which will then be reboadcast in the Sim
|
||||
|
||||
m_log.Info("[IRC]: ExtractMsg: " + input);
|
||||
Dictionary<string, string> result = null;
|
||||
string regex = @":(?<nick>\w*)!~(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)";
|
||||
//string regex = @":(?<nick>\w*)!~(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)";
|
||||
string regex = @":(?<nick>\w*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)";
|
||||
Regex RE = new Regex(regex, RegexOptions.Multiline);
|
||||
MatchCollection matches = RE.Matches(input);
|
||||
// Get some direct matches $1 $4 is a
|
||||
|
@ -311,10 +529,10 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
else
|
||||
{
|
||||
m_log.Verbose("IRC", "Number of matches: " + matches.Count);
|
||||
m_log.Info("[IRC]: Number of matches: " + matches.Count);
|
||||
if (matches.Count > 0)
|
||||
{
|
||||
m_log.Verbose("IRC", "Number of groups: " + matches[0].Groups.Count);
|
||||
m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -322,13 +540,30 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public void PingRun()
|
||||
{
|
||||
// IRC keep alive thread
|
||||
// send PING ever 15 seconds
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_connected == true)
|
||||
{
|
||||
m_writer.WriteLine("PING :" + m_server);
|
||||
m_writer.Flush();
|
||||
Thread.Sleep(15000);
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)");
|
||||
Reconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ListenerRun()
|
||||
{
|
||||
|
@ -336,12 +571,15 @@ namespace OpenSim.Region.Environment.Modules
|
|||
LLVector3 pos = new LLVector3(128, 128, 20);
|
||||
while (true)
|
||||
{
|
||||
while ((inputLine = m_reader.ReadLine()) != null)
|
||||
try
|
||||
{
|
||||
while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null))
|
||||
{
|
||||
// Console.WriteLine(inputLine);
|
||||
if (inputLine.Contains(m_channel))
|
||||
{
|
||||
Dictionary<string, string> data = ExtractMsg(inputLine);
|
||||
// Any chat ???
|
||||
if (data != null)
|
||||
{
|
||||
foreach (Scene m_scene in m_scenes)
|
||||
|
@ -357,15 +595,239 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Was an command from the IRC server
|
||||
ProcessIRCCommand(inputLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Was an command from the IRC server
|
||||
ProcessIRCCommand(inputLine);
|
||||
}
|
||||
Thread.Sleep(150);
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)");
|
||||
Reconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace);
|
||||
}
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
public void BroadcastSim(string message,string sender)
|
||||
{
|
||||
LLVector3 pos = new LLVector3(128, 128, 20);
|
||||
try
|
||||
{
|
||||
foreach (Scene m_scene in m_scenes)
|
||||
{
|
||||
m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
|
||||
{
|
||||
if (!avatar.IsChildAgent)
|
||||
{
|
||||
avatar.ControllingClient.SendChatMessage(
|
||||
Helpers.StringToField(message), 255,
|
||||
pos, sender,
|
||||
LLUUID.Zero);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex) // IRC gate should not crash Sim
|
||||
{
|
||||
m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public enum ErrorReplies
|
||||
{
|
||||
NotRegistered = 451, // ":You have not registered"
|
||||
NicknameInUse = 433 // "<nick> :Nickname is already in use"
|
||||
}
|
||||
|
||||
public enum Replies
|
||||
{
|
||||
MotdStart = 375, // ":- <server> Message of the day - "
|
||||
Motd = 372, // ":- <text>"
|
||||
EndOfMotd = 376 // ":End of /MOTD command"
|
||||
}
|
||||
|
||||
public void ProcessIRCCommand(string command)
|
||||
{
|
||||
//m_log.Info("[IRC]: ProcessIRCCommand:" + command);
|
||||
|
||||
string[] commArgs = new string[command.Split(' ').Length];
|
||||
string c_server = m_server;
|
||||
|
||||
commArgs = command.Split(' ');
|
||||
if (commArgs[0].Substring(0, 1) == ":")
|
||||
{
|
||||
commArgs[0] = commArgs[0].Remove(0, 1);
|
||||
}
|
||||
|
||||
if (commArgs[1] == "002")
|
||||
{
|
||||
// fetch the correct servername
|
||||
// ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/...
|
||||
// irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch
|
||||
|
||||
c_server = (commArgs[6].Split('['))[0];
|
||||
m_server = c_server;
|
||||
}
|
||||
|
||||
if (commArgs[0] == "ERROR")
|
||||
{
|
||||
m_log.Error("[IRC]: IRC SERVER ERROR:" + command);
|
||||
}
|
||||
|
||||
if (commArgs[0] == "PING")
|
||||
{
|
||||
string p_reply = "";
|
||||
|
||||
for (int i = 1; i < commArgs.Length; i++)
|
||||
{
|
||||
p_reply += commArgs[i] + " ";
|
||||
}
|
||||
|
||||
m_writer.WriteLine("PONG " + p_reply);
|
||||
m_writer.Flush();
|
||||
|
||||
}
|
||||
else if (commArgs[0] == c_server)
|
||||
{
|
||||
// server message
|
||||
try
|
||||
{
|
||||
Int32 commandCode = Int32.Parse(commArgs[1]);
|
||||
switch (commandCode)
|
||||
{
|
||||
case (int)ErrorReplies.NicknameInUse:
|
||||
// Gen a new name
|
||||
m_nick = m_basenick + Util.RandomClass.Next(1, 99);
|
||||
m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick);
|
||||
// Retry
|
||||
m_writer.WriteLine("NICK " + m_nick);
|
||||
m_writer.Flush();
|
||||
m_writer.WriteLine("JOIN " + m_channel);
|
||||
m_writer.Flush();
|
||||
break;
|
||||
case (int)ErrorReplies.NotRegistered:
|
||||
break;
|
||||
case (int)Replies.EndOfMotd:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal message
|
||||
string commAct = commArgs[1];
|
||||
switch (commAct)
|
||||
{
|
||||
case "JOIN": eventIrcJoin(commArgs); break;
|
||||
case "PART": eventIrcPart(commArgs); break;
|
||||
case "MODE": eventIrcMode(commArgs); break;
|
||||
case "NICK": eventIrcNickChange(commArgs); break;
|
||||
case "KICK": eventIrcKick(commArgs); break;
|
||||
case "QUIT": eventIrcQuit(commArgs); break;
|
||||
case "PONG": break; // that's nice
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void eventIrcJoin(string[] commArgs)
|
||||
{
|
||||
string IrcChannel = commArgs[2];
|
||||
string IrcUser = commArgs[0].Split('!')[0];
|
||||
BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick);
|
||||
|
||||
}
|
||||
|
||||
public void eventIrcPart(string[] commArgs)
|
||||
{
|
||||
string IrcChannel = commArgs[2];
|
||||
string IrcUser = commArgs[0].Split('!')[0];
|
||||
BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick);
|
||||
|
||||
}
|
||||
public void eventIrcMode(string[] commArgs)
|
||||
{
|
||||
string IrcChannel = commArgs[2];
|
||||
string IrcUser = commArgs[0].Split('!')[0];
|
||||
string UserMode = "";
|
||||
for (int i = 3; i < commArgs.Length; i++)
|
||||
{
|
||||
UserMode += commArgs[i] + " ";
|
||||
}
|
||||
|
||||
if (UserMode.Substring(0, 1) == ":")
|
||||
{
|
||||
UserMode = UserMode.Remove(0, 1);
|
||||
}
|
||||
|
||||
}
|
||||
public void eventIrcNickChange(string[] commArgs)
|
||||
{
|
||||
string UserOldNick = commArgs[0].Split('!')[0];
|
||||
string UserNewNick = commArgs[2].Remove(0, 1);
|
||||
BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick);
|
||||
|
||||
}
|
||||
|
||||
public void eventIrcKick(string[] commArgs)
|
||||
{
|
||||
string UserKicker = commArgs[0].Split('!')[0];
|
||||
string UserKicked = commArgs[3];
|
||||
string IrcChannel = commArgs[2];
|
||||
string KickMessage = "";
|
||||
for (int i = 4; i < commArgs.Length; i++)
|
||||
{
|
||||
KickMessage += commArgs[i] + " ";
|
||||
}
|
||||
BroadcastSim(UserKicker + " kicked " + UserKicked +" on "+IrcChannel+" saying "+KickMessage, m_nick);
|
||||
if (UserKicked == m_nick)
|
||||
{
|
||||
BroadcastSim("Hey, that was me!!!", m_nick);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void eventIrcQuit(string[] commArgs)
|
||||
{
|
||||
string IrcUser = commArgs[0].Split('!')[0];
|
||||
string QuitMessage = "";
|
||||
|
||||
for (int i = 2; i < commArgs.Length; i++)
|
||||
{
|
||||
QuitMessage += commArgs[i] + " ";
|
||||
}
|
||||
BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Close()
|
||||
{
|
||||
m_connected = false;
|
||||
m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing");
|
||||
m_writer.Flush();
|
||||
listener.Abort();
|
||||
pingSender.Abort();
|
||||
m_writer.Close();
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -176,7 +176,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
asset.Type = 0;
|
||||
asset.Description = "dynamic image";
|
||||
asset.Local = false;
|
||||
asset.Temporary = false;
|
||||
asset.Temporary = true;
|
||||
scene.AssetCache.AddAsset(asset);
|
||||
|
||||
LastAssetID = asset.FullID;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -40,8 +40,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
public class FriendsModule : IRegionModule
|
||||
{
|
||||
|
||||
private LogBase m_log;
|
||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
|
||||
|
@ -49,7 +48,6 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
m_log = MainLog.Instance;
|
||||
m_scene = scene;
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage;
|
||||
|
@ -72,6 +70,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
|
||||
}
|
||||
|
||||
private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID,
|
||||
LLUUID fromAgentSession, LLUUID toAgentID,
|
||||
LLUUID imSessionID, uint timestamp, string fromAgentName,
|
||||
|
@ -89,13 +88,13 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
|
||||
|
||||
m_log.Verbose("FRIEND", "38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||
m_log.Info("[FRIEND]: 38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||
GridInstantMessage msg = new GridInstantMessage();
|
||||
msg.fromAgentID = fromAgentID.UUID;
|
||||
msg.fromAgentSession = fromAgentSession.UUID;
|
||||
msg.toAgentID = toAgentID.UUID;
|
||||
msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here
|
||||
m_log.Verbose("FRIEND","Filling Session: " + msg.imSessionID.ToString());
|
||||
m_log.Info("[FRIEND]: Filling Session: " + msg.imSessionID.ToString());
|
||||
msg.timestamp = timestamp;
|
||||
if (client != null)
|
||||
{
|
||||
|
@ -115,20 +114,18 @@ namespace OpenSim.Region.Environment.Modules
|
|||
msg.binaryBucket = binaryBucket;
|
||||
m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
|
||||
}
|
||||
if (dialog == (byte)39)
|
||||
{
|
||||
m_log.Verbose("FRIEND", "38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||
|
||||
}
|
||||
if (dialog == (byte)40)
|
||||
{
|
||||
m_log.Verbose("FRIEND", "38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||
}
|
||||
|
||||
// 39 == Accept Friendship
|
||||
if (dialog == (byte)39)
|
||||
{
|
||||
m_log.Info("[FRIEND]: 39 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||
}
|
||||
|
||||
// 40 == Decline Friendship
|
||||
|
||||
if (dialog == (byte)40)
|
||||
{
|
||||
m_log.Info("[FRIEND]: 40 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List<LLUUID> callingCardFolders)
|
||||
|
@ -160,6 +157,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
// TODO: Inform agent that the friend is online
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List<LLUUID> callingCardFolders)
|
||||
{
|
||||
if (m_pendingFriendRequests.ContainsKey(transactionID))
|
||||
|
@ -184,20 +182,15 @@ namespace OpenSim.Region.Environment.Modules
|
|||
msg.binaryBucket = new byte[0];
|
||||
m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
|
||||
m_pendingFriendRequests.Remove(transactionID);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void OnTerminateFriendship(IClientAPI client, LLUUID agent, LLUUID exfriendID)
|
||||
{
|
||||
m_scene.StoreRemoveFriendship(agent, exfriendID);
|
||||
// TODO: Inform the client that the ExFriend is offline
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||
{
|
||||
// Trigger the above event handler
|
||||
|
@ -206,16 +199,12 @@ namespace OpenSim.Region.Environment.Modules
|
|||
msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
|
||||
new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
|
||||
msg.binaryBucket);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -27,18 +27,182 @@
|
|||
*/
|
||||
|
||||
using Nini.Config;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Region.Environment.Interfaces;
|
||||
using OpenSim.Region.Environment.Scenes;
|
||||
using libsecondlife;
|
||||
|
||||
namespace OpenSim.Region.Environment.Modules
|
||||
{
|
||||
public class GroupsModule : IRegionModule
|
||||
{
|
||||
private Scene m_scene;
|
||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private List<Scene> m_scene = new List<Scene>();
|
||||
private Dictionary<LLUUID, IClientAPI> m_iclientmap = new Dictionary<LLUUID, IClientAPI>();
|
||||
private Dictionary<LLUUID, GroupData> m_groupmap = new Dictionary<LLUUID, GroupData>();
|
||||
private Dictionary<LLUUID, GroupList> m_grouplistmap = new Dictionary<LLUUID, GroupList>();
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
m_scene = scene;
|
||||
lock (m_scene)
|
||||
{
|
||||
m_scene.Add(scene);
|
||||
}
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnClientClosed += OnClientClosed;
|
||||
scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage;
|
||||
//scene.EventManager.
|
||||
}
|
||||
private void OnNewClient(IClientAPI client)
|
||||
{
|
||||
// All friends establishment protocol goes over instant message
|
||||
// There's no way to send a message from the sim
|
||||
// to a user to 'add a friend' without causing dialog box spam
|
||||
//
|
||||
// The base set of friends are added when the user signs on in their XMLRPC response
|
||||
// Generated by LoginService. The friends are retreived from the database by the UserManager
|
||||
|
||||
// Subscribe to instant messages
|
||||
client.OnInstantMessage += OnInstantMessage;
|
||||
client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
|
||||
lock (m_iclientmap)
|
||||
{
|
||||
if (!m_iclientmap.ContainsKey(client.AgentId))
|
||||
{
|
||||
m_iclientmap.Add(client.AgentId, client);
|
||||
}
|
||||
}
|
||||
GroupData OpenSimulatorGroup = new GroupData();
|
||||
OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester";
|
||||
OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120");
|
||||
OpenSimulatorGroup.GroupMembers.Add(client.AgentId);
|
||||
OpenSimulatorGroup.groupName = "OpenSimulator Testing";
|
||||
OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome;
|
||||
OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester");
|
||||
lock (m_groupmap)
|
||||
{
|
||||
if (!m_groupmap.ContainsKey(client.AgentId))
|
||||
{
|
||||
m_groupmap.Add(client.AgentId, OpenSimulatorGroup);
|
||||
}
|
||||
}
|
||||
GroupList testGroupList = new GroupList();
|
||||
testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120"));
|
||||
|
||||
lock (m_grouplistmap)
|
||||
{
|
||||
if (!m_grouplistmap.ContainsKey(client.AgentId))
|
||||
{
|
||||
m_grouplistmap.Add(client.AgentId, testGroupList);
|
||||
}
|
||||
}
|
||||
m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group");
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID)
|
||||
{
|
||||
string firstname = remoteClient.FirstName;
|
||||
string lastname = remoteClient.LastName;
|
||||
|
||||
LLUUID ActiveGroupID = LLUUID.Zero;
|
||||
uint ActiveGroupPowers = 0;
|
||||
string ActiveGroupName = "";
|
||||
string ActiveGroupTitle = "";
|
||||
|
||||
bool foundUser = false;
|
||||
|
||||
lock (m_iclientmap)
|
||||
{
|
||||
if (m_iclientmap.ContainsKey(remoteClient.AgentId))
|
||||
{
|
||||
foundUser = true;
|
||||
}
|
||||
}
|
||||
if (foundUser)
|
||||
{
|
||||
lock (m_groupmap)
|
||||
{
|
||||
if (m_groupmap.ContainsKey(remoteClient.AgentId))
|
||||
{
|
||||
GroupData grp = m_groupmap[remoteClient.AgentId];
|
||||
if (grp != null)
|
||||
{
|
||||
ActiveGroupID = grp.GroupID;
|
||||
ActiveGroupName = grp.groupName;
|
||||
ActiveGroupPowers = grp.groupPowers;
|
||||
ActiveGroupTitle = grp.ActiveGroupTitle;
|
||||
}
|
||||
|
||||
//remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
|
||||
LLUUID fromAgentSession, LLUUID toAgentID,
|
||||
LLUUID imSessionID, uint timestamp, string fromAgentName,
|
||||
string message, byte dialog, bool fromGroup, byte offline,
|
||||
uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
|
||||
byte[] binaryBucket)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||
{
|
||||
// Trigger the above event handler
|
||||
OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
|
||||
new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
|
||||
msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
|
||||
new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
|
||||
msg.binaryBucket);
|
||||
}
|
||||
|
||||
private void OnClientClosed(LLUUID agentID)
|
||||
{
|
||||
lock (m_iclientmap)
|
||||
{
|
||||
if (m_iclientmap.ContainsKey(agentID))
|
||||
{
|
||||
IClientAPI cli = m_iclientmap[agentID];
|
||||
if (cli != null)
|
||||
{
|
||||
m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString());
|
||||
}
|
||||
m_iclientmap.Remove(agentID);
|
||||
}
|
||||
}
|
||||
|
||||
lock (m_groupmap)
|
||||
{
|
||||
if (m_groupmap.ContainsKey(agentID))
|
||||
{
|
||||
m_groupmap.Remove(agentID);
|
||||
}
|
||||
}
|
||||
|
||||
lock (m_grouplistmap)
|
||||
{
|
||||
if (m_grouplistmap.ContainsKey(agentID))
|
||||
{
|
||||
m_grouplistmap.Remove(agentID);
|
||||
}
|
||||
}
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
|
@ -47,6 +211,22 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public void Close()
|
||||
{
|
||||
m_log.Info("[GROUP]: Shutting down group module.");
|
||||
lock (m_iclientmap)
|
||||
{
|
||||
m_iclientmap.Clear();
|
||||
}
|
||||
|
||||
lock (m_groupmap)
|
||||
{
|
||||
m_groupmap.Clear();
|
||||
}
|
||||
|
||||
lock (m_grouplistmap)
|
||||
{
|
||||
m_grouplistmap.Clear();
|
||||
}
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
public string Name
|
||||
|
@ -56,7 +236,44 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public bool IsSharedModule
|
||||
{
|
||||
get { return false; }
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
}
|
||||
public class GroupData
|
||||
{
|
||||
public LLUUID GroupID;
|
||||
public string groupName;
|
||||
public string ActiveGroupTitle;
|
||||
public List<string> GroupTitles;
|
||||
public List<LLUUID> GroupMembers;
|
||||
public uint groupPowers = (uint)(GroupPowers.LandAllowLandmark | GroupPowers.LandAllowSetHome);
|
||||
|
||||
public GroupPowers ActiveGroupPowers
|
||||
{
|
||||
set
|
||||
{
|
||||
groupPowers = (uint) value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return (GroupPowers)groupPowers;
|
||||
}
|
||||
}
|
||||
|
||||
public GroupData()
|
||||
{
|
||||
GroupTitles = new List<string>();
|
||||
GroupMembers = new List<LLUUID>();
|
||||
}
|
||||
|
||||
}
|
||||
public class GroupList
|
||||
{
|
||||
public List<LLUUID> m_GroupList;
|
||||
public GroupList()
|
||||
{
|
||||
m_GroupList = new List<LLUUID>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -39,12 +39,6 @@ namespace OpenSim.Region.Environment.Modules
|
|||
public class InstantMessageModule : IRegionModule
|
||||
{
|
||||
private List<Scene> m_scenes = new List<Scene>();
|
||||
private LogBase m_log;
|
||||
|
||||
public InstantMessageModule()
|
||||
{
|
||||
m_log = MainLog.Instance;
|
||||
}
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
|
@ -68,7 +62,6 @@ namespace OpenSim.Region.Environment.Modules
|
|||
uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
|
||||
byte[] binaryBucket)
|
||||
{
|
||||
|
||||
bool FriendDialog = ((dialog == (byte)38) || (dialog == (byte)39) || (dialog == (byte)40));
|
||||
|
||||
// IM dialogs need to be pre-processed and have their sessionID filled by the server
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
|
|
@ -126,7 +126,35 @@ namespace OpenSim.Region.Environment.Modules
|
|||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
Bitmap image = new Bitmap(response.GetResponseStream());
|
||||
Bitmap resize = new Bitmap(image, new Size(512, 512));
|
||||
Size newsize;
|
||||
|
||||
// TODO: make this a bit less hard coded
|
||||
if ((image.Height < 64) && (image.Width < 64))
|
||||
{
|
||||
newsize = new Size(32, 32);
|
||||
}
|
||||
else if ((image.Height < 128) && (image.Width < 128))
|
||||
{
|
||||
newsize = new Size(64, 64);
|
||||
}
|
||||
else if ((image.Height <256) && (image.Width < 256))
|
||||
{
|
||||
newsize = new Size(128, 128);
|
||||
}
|
||||
else if ((image.Height < 512 && image.Width < 512))
|
||||
{
|
||||
newsize = new Size(256, 256);
|
||||
}
|
||||
else if ((image.Height < 1024 && image.Width < 1024))
|
||||
{
|
||||
newsize = new Size(512, 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
newsize = new Size(1024,1024);
|
||||
}
|
||||
|
||||
Bitmap resize = new Bitmap(image, newsize);
|
||||
byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
|
||||
|
||||
m_textureManager.ReturnData(state.RequestID, imageJ2000);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -88,7 +88,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
|
||||
private object HttpListLock = new object();
|
||||
private string m_name = "HttpScriptRequests";
|
||||
private int httpTimeout = 300;
|
||||
private int httpTimeout = 30000;
|
||||
|
||||
// <request id, HttpRequestClass>
|
||||
private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests;
|
||||
|
@ -184,6 +184,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public void StopHttpRequest(uint m_localID, LLUUID m_itemID)
|
||||
{
|
||||
if(m_pendingRequests != null) {
|
||||
lock (HttpListLock)
|
||||
{
|
||||
HttpRequestClass tmpReq;
|
||||
|
@ -194,6 +195,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO
|
||||
|
@ -216,7 +218,6 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
if (tmpReq.finished)
|
||||
{
|
||||
m_pendingRequests.Remove(luid);
|
||||
return tmpReq;
|
||||
}
|
||||
}
|
||||
|
@ -224,6 +225,21 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveCompletedRequest(LLUUID id)
|
||||
{
|
||||
lock (HttpListLock)
|
||||
{
|
||||
HttpRequestClass tmpReq;
|
||||
if (m_pendingRequests.TryGetValue(id, out tmpReq))
|
||||
{
|
||||
tmpReq.Stop();
|
||||
tmpReq = null;
|
||||
m_pendingRequests.Remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -269,7 +285,9 @@ namespace OpenSim.Region.Environment.Modules
|
|||
httpThread.Name = "HttpRequestThread";
|
||||
httpThread.Priority = ThreadPriority.BelowNormal;
|
||||
httpThread.IsBackground = true;
|
||||
finished = false;
|
||||
httpThread.Start();
|
||||
OpenSim.Framework.ThreadTracker.Add(httpThread);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -39,6 +39,8 @@ 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;
|
||||
|
@ -48,7 +50,6 @@ namespace OpenSim.Region.Environment.Modules
|
|||
private long m_start;
|
||||
|
||||
private Scene m_scene;
|
||||
private LogBase m_log;
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
|
@ -69,7 +70,6 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
m_dilation = (int) (m_real_day/m_day_length);
|
||||
m_scene = scene;
|
||||
m_log = MainLog.Instance;
|
||||
scene.EventManager.OnFrame += SunUpdate;
|
||||
scene.EventManager.OnNewClient += SunToClient;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_frame++;
|
||||
return;
|
||||
}
|
||||
// m_log.Verbose("SUN","I've got an update {0} => {1}", m_scene.RegionsInfo.RegionName, HourOfTheDay());
|
||||
// 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)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING 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 System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Region.Environment.Modules;
|
||||
using OpenSim.Region.Environment.Interfaces;
|
||||
using OpenSim.Region.Environment.Scenes;
|
||||
using libsecondlife;
|
||||
|
||||
namespace OpenSim.Region.Environment.Modules.Terrain
|
||||
{
|
||||
/// <summary>
|
||||
/// A new version of the old Channel class, simplified
|
||||
/// </summary>
|
||||
public class TerrainChannel : ITerrainChannel
|
||||
{
|
||||
private double[,] map;
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return map.GetLength(0); }
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return map.GetLength(1); }
|
||||
}
|
||||
|
||||
public TerrainChannel Copy()
|
||||
{
|
||||
TerrainChannel copy = new TerrainChannel(false);
|
||||
copy.map = (double[,])this.map.Clone();
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
public double this[int x, int y]
|
||||
{
|
||||
get
|
||||
{
|
||||
return map[x, y];
|
||||
}
|
||||
set
|
||||
{
|
||||
map[x, y] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public TerrainChannel()
|
||||
{
|
||||
map = new double[Constants.RegionSize, Constants.RegionSize];
|
||||
}
|
||||
|
||||
public TerrainChannel(bool createMap)
|
||||
{
|
||||
if (createMap)
|
||||
map = new double[Constants.RegionSize, Constants.RegionSize];
|
||||
}
|
||||
|
||||
public TerrainChannel(int w, int h)
|
||||
{
|
||||
map = new double[w, h];
|
||||
}
|
||||
}
|
||||
|
||||
public class TerrainModule : IRegionModule
|
||||
{
|
||||
Scene m_scene;
|
||||
|
||||
private IConfigSource m_gConfig;
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
m_scene = scene;
|
||||
m_gConfig = config;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "TerrainModule"; }
|
||||
}
|
||||
|
||||
public bool IsSharedModule
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -41,14 +41,22 @@ namespace OpenSim.Region.Environment.Modules
|
|||
//this is a first attempt, to start breaking the mess thats called the assetcache up.
|
||||
// basically this should be the texture sending (to clients) code moved out of assetcache
|
||||
//and some small clean up
|
||||
// but on first tests it didn't seem to work very well so is currently not in use.
|
||||
public class TextureDownloadModule : IRegionModule
|
||||
{
|
||||
//private static readonly log4net.ILog m_log
|
||||
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
private List<Scene> m_scenes = new List<Scene>();
|
||||
|
||||
/// <summary>
|
||||
/// There is one queue for all textures waiting to be sent, regardless of the requesting user.
|
||||
/// </summary>
|
||||
private readonly BlockingQueue<TextureSender> m_queueSenders = new BlockingQueue<TextureSender>();
|
||||
|
||||
/// <summary>
|
||||
/// Each user has their own texture download service.
|
||||
/// </summary>
|
||||
private readonly Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices =
|
||||
new Dictionary<LLUUID, UserTextureDownloadService>();
|
||||
|
||||
|
@ -64,8 +72,10 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
//Console.WriteLine("Creating Texture download module");
|
||||
m_thread = new Thread(new ThreadStart(ProcessTextureSenders));
|
||||
m_thread.Name = "ProcessTextureSenderThread";
|
||||
m_thread.IsBackground = true;
|
||||
m_thread.Start();
|
||||
OpenSim.Framework.ThreadTracker.Add(m_thread);
|
||||
}
|
||||
|
||||
if (!m_scenes.Contains(scene))
|
||||
|
@ -77,13 +87,17 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup the texture service related objects for the removed presence.
|
||||
/// </summary>
|
||||
/// <param name="agentId"> </param>
|
||||
private void EventManager_OnRemovePresence(LLUUID agentId)
|
||||
{
|
||||
UserTextureDownloadService textureService;
|
||||
|
||||
lock (m_userTextureServices)
|
||||
{
|
||||
if( m_userTextureServices.TryGetValue( agentId, out textureService ))
|
||||
if (m_userTextureServices.TryGetValue(agentId, out textureService))
|
||||
{
|
||||
textureService.Close();
|
||||
|
||||
|
@ -115,6 +129,12 @@ namespace OpenSim.Region.Environment.Modules
|
|||
client.OnRequestTexture += TextureRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does this user have a registered texture download service?
|
||||
/// </summary>
|
||||
/// <param name="userID"></param>
|
||||
/// <param name="textureService"></param>
|
||||
/// <returns>Always returns true, since a service is created if one does not already exist</returns>
|
||||
private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService)
|
||||
{
|
||||
lock (m_userTextureServices)
|
||||
|
@ -130,6 +150,11 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the process of requesting a given texture.
|
||||
/// </summary>
|
||||
/// <param name="sender"> </param>
|
||||
/// <param name="e"></param>
|
||||
public void TextureRequest(Object sender, TextureRequestArgs e)
|
||||
{
|
||||
IClientAPI client = (IClientAPI) sender;
|
||||
|
@ -140,11 +165,17 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entry point for the thread dedicated to processing the texture queue.
|
||||
/// </summary>
|
||||
public void ProcessTextureSenders()
|
||||
{
|
||||
TextureSender sender = null;
|
||||
|
||||
while (true)
|
||||
{
|
||||
TextureSender sender = m_queueSenders.Dequeue();
|
||||
sender = m_queueSenders.Dequeue();
|
||||
|
||||
if (sender.Cancel)
|
||||
{
|
||||
TextureSent(sender);
|
||||
|
@ -163,12 +194,23 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_queueSenders.Enqueue(sender);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that any sender we currently have can get garbage collected
|
||||
sender = null;
|
||||
|
||||
//m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the texture has finished sending.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
private void TextureSent(TextureSender sender)
|
||||
{
|
||||
sender.Sending = false;
|
||||
//m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID);
|
||||
m_scene.AddPendingDownloads(-1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE 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 libsecondlife;
|
||||
using libsecondlife.Packets;
|
||||
|
@ -6,33 +34,61 @@ using OpenSim.Framework.Console;
|
|||
|
||||
namespace OpenSim.Region.Environment.Modules
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class TextureSender
|
||||
{
|
||||
private static readonly log4net.ILog m_log
|
||||
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Records the number of times texture send has been called.
|
||||
/// </summary>
|
||||
public int counter = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the texture asset to send.
|
||||
/// </summary>
|
||||
private AssetBase m_asset;
|
||||
public long DataPointer = 0;
|
||||
public int NumPackets = 0;
|
||||
public int PacketCounter = 0;
|
||||
|
||||
//public LLUUID assetID { get { return m_asset.FullID; } }
|
||||
|
||||
/// <summary>
|
||||
/// This is actually the number of extra packets required to send the texture data! We always assume
|
||||
/// at least one is required.
|
||||
/// </summary>
|
||||
private int NumPackets = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts
|
||||
/// at the 600th byte (0th indexed).
|
||||
/// </summary>
|
||||
private int PacketCounter = 0;
|
||||
|
||||
public bool Cancel = false;
|
||||
public bool ImageLoaded = false;
|
||||
|
||||
public bool Sending = false;
|
||||
|
||||
public IClientAPI RequestUser;
|
||||
public LLUUID RequestedAssetID;
|
||||
public int RequestedDiscardLevel = -1;
|
||||
public uint StartPacketNumber = 0;
|
||||
private IClientAPI RequestUser;
|
||||
|
||||
// private int m_sentDiscardLevel = -1;
|
||||
private int RequestedDiscardLevel = -1;
|
||||
private uint StartPacketNumber = 0;
|
||||
|
||||
public TextureSender(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber)
|
||||
public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
|
||||
{
|
||||
RequestUser = client;
|
||||
RequestedAssetID = textureID;
|
||||
RequestedDiscardLevel = discardLevel;
|
||||
StartPacketNumber = packetNumber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load up the texture data to send.
|
||||
/// </summary>
|
||||
/// <param name="asset">
|
||||
/// A <see cref="AssetBase"/>
|
||||
/// </param>
|
||||
public void TextureReceived(AssetBase asset)
|
||||
{
|
||||
m_asset = asset;
|
||||
|
@ -48,6 +104,10 @@ namespace OpenSim.Region.Environment.Modules
|
|||
PacketCounter = (int) StartPacketNumber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a texture packet to the client.
|
||||
/// </summary>
|
||||
/// <returns>True if the last packet has been sent, false otherwise.</returns>
|
||||
public bool SendTexturePacket()
|
||||
{
|
||||
SendPacket();
|
||||
|
@ -60,6 +120,9 @@ namespace OpenSim.Region.Environment.Modules
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a texture packet to the client.
|
||||
/// </summary>
|
||||
private void SendPacket()
|
||||
{
|
||||
if (PacketCounter <= NumPackets)
|
||||
|
@ -107,8 +170,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
MainLog.Instance.Error("TEXTURE",
|
||||
"Unable to separate texture into multiple packets: Array bounds failure on asset:" +
|
||||
m_log.Error("[TEXTURE]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
|
||||
m_asset.FullID.ToString() );
|
||||
return;
|
||||
}
|
||||
|
@ -118,6 +180,12 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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...
|
||||
/// </summary>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
private int CalculateNumPackets(int length)
|
||||
{
|
||||
int numPackets = 0;
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE 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.Framework.Console;
|
||||
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 log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.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);
|
||||
|
||||
System.Timers.Timer CalculateTrees = new System.Timers.Timer(m_tree_updates);
|
||||
CalculateTrees.Elapsed += new System.Timers.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 Axiom.Math.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.Terrain.heightmap.Get((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, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
growTrees();
|
||||
seedTrees();
|
||||
killTrees();
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
{
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "TreePopulatorModule"; }
|
||||
}
|
||||
|
||||
public bool IsSharedModule
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSim Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE 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;
|
||||
|
@ -7,10 +35,27 @@ using OpenSim.Region.Environment.Scenes;
|
|||
|
||||
namespace OpenSim.Region.Environment.Modules
|
||||
{
|
||||
/// <summary>
|
||||
/// This module sets up texture senders in response to client texture requests, and places them on a
|
||||
/// processing queue once those senders have the appropriate data (i.e. a texture retrieved from the
|
||||
/// asset cache).
|
||||
/// </summary>
|
||||
public class UserTextureDownloadService
|
||||
{
|
||||
private static readonly log4net.ILog m_log
|
||||
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Holds texture senders before they have received the appropriate texture from the asset cache.
|
||||
/// </summary>
|
||||
private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
|
||||
|
||||
/// <summary>
|
||||
/// Texture Senders are placed in this queue once they have received their texture from the asset
|
||||
/// cache. Another module actually invokes the send.
|
||||
/// </summary>
|
||||
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
|
||||
|
||||
private readonly Scene m_scene;
|
||||
|
||||
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue)
|
||||
|
@ -19,6 +64,12 @@ namespace OpenSim.Region.Environment.Modules
|
|||
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>
|
||||
/// <param name="client"> </param>
|
||||
/// <param name="e"></param>
|
||||
public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
|
||||
{
|
||||
TextureSender textureSender;
|
||||
|
@ -30,20 +81,20 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
|
||||
{
|
||||
// If we've received new non UUID information for this request and it hasn't dispatched
|
||||
// yet, then update the request accordingly.
|
||||
textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
|
||||
|
||||
if ((textureSender.ImageLoaded) &&
|
||||
(textureSender.Sending == false))
|
||||
{
|
||||
EnqueueTextureSender(textureSender);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//m_log.DebugFormat("[USER TEXTURE DOWNLOAD]: Adding download stat {0}", e.RequestedAssetID);
|
||||
m_scene.AddPendingDownloads(1);
|
||||
|
||||
TextureSender requestHandler =
|
||||
new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber);
|
||||
new TextureSender(client, e.DiscardLevel, e.PacketNumber);
|
||||
m_textureSenders.Add(e.RequestedAssetID, requestHandler);
|
||||
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback);
|
||||
|
||||
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,28 +110,56 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
|
||||
public void TextureCallback(LLUUID textureID, AssetBase asset)
|
||||
/// <summary>
|
||||
/// The callback for the asset cache when a texture has been retrieved. This method queues the
|
||||
/// texture sender for processing.
|
||||
/// </summary>
|
||||
/// <param name="textureID"></param>
|
||||
/// <param name="asset"></param>
|
||||
public void TextureCallback(LLUUID textureID, AssetBase texture)
|
||||
{
|
||||
lock (m_textureSenders)
|
||||
{
|
||||
TextureSender textureSender;
|
||||
|
||||
if (m_textureSenders.TryGetValue(textureID, out textureSender))
|
||||
{
|
||||
if (null != texture)
|
||||
{
|
||||
if (!textureSender.ImageLoaded)
|
||||
{
|
||||
textureSender.TextureReceived(asset);
|
||||
|
||||
textureSender.TextureReceived(texture);
|
||||
EnqueueTextureSender(textureSender);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Got a texture with no sender object to handle it, this shouldn't happen");
|
||||
// Right now, leaving it up to lower level asset server code to post the fact that
|
||||
// this texture could not be found
|
||||
|
||||
// TODO Send packet back to the client telling it not to expect the texture
|
||||
|
||||
//m_log.DebugFormat("[USER TEXTURE DOWNLOAD]: Removing download stat for {0}", textureID);
|
||||
m_scene.AddPendingDownloads(-1);
|
||||
}
|
||||
|
||||
//m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID);
|
||||
m_textureSenders.Remove(textureID);
|
||||
//m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"Got a texture uuid {0} with no sender object to handle it, this shouldn't happen",
|
||||
textureID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place a ready texture sender on the processing queue.
|
||||
/// </summary>
|
||||
/// <param name="textureSender"></param>
|
||||
private void EnqueueTextureSender(TextureSender textureSender)
|
||||
{
|
||||
textureSender.Cancel = false;
|
||||
|
@ -93,6 +172,9 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close this module.
|
||||
/// </summary>
|
||||
internal void Close()
|
||||
{
|
||||
lock (m_textureSenders)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -70,6 +70,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
private Scene m_scene;
|
||||
private object CommListLock = new object();
|
||||
private object ListLock = new object();
|
||||
private string m_name = "WorldCommModule";
|
||||
private ListenerManager m_listenerManager;
|
||||
private Queue<ListenerInfo> m_pending;
|
||||
|
@ -83,8 +84,8 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_scene = scene;
|
||||
m_scene.RegisterModuleInterface<IWorldComm>(this);
|
||||
m_listenerManager = new ListenerManager();
|
||||
m_pending = new Queue<ListenerInfo>();
|
||||
m_scene.EventManager.OnNewClient += NewClient;
|
||||
m_pending = new Queue<ListenerInfo>();
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
|
@ -136,6 +137,18 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_listenerManager.Remove(handle);
|
||||
}
|
||||
|
||||
public void DeleteListener(LLUUID itemID)
|
||||
{
|
||||
if (m_listenerManager != null)
|
||||
{
|
||||
lock (ListLock)
|
||||
{
|
||||
m_listenerManager.DeleteListener(itemID);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This method scans nearby objects and determines if they are listeners,
|
||||
// and if so if this message fits the filter. If it does, then
|
||||
// enqueue the message for delivery to the objects listen event handler.
|
||||
|
@ -157,16 +170,16 @@ namespace OpenSim.Region.Environment.Modules
|
|||
// If they are in proximity, then if they are
|
||||
// listeners, if so add them to the pending queue
|
||||
|
||||
lock (m_scene.Entities)
|
||||
foreach (ListenerInfo li in m_listenerManager.GetListeners())
|
||||
{
|
||||
foreach (LLUUID eb in m_scene.Entities.Keys)
|
||||
{
|
||||
EntityBase sPart;
|
||||
|
||||
m_scene.Entities.TryGetValue(eb, out sPart);
|
||||
m_scene.Entities.TryGetValue(li.GetHostID(), out sPart);
|
||||
|
||||
// Dont process if this message is from itself!
|
||||
if (eb.ToString().Equals(sourceItemID) ||
|
||||
if (li.GetHostID().ToString().Equals(sourceItemID) ||
|
||||
sPart.UUID.ToString().Equals(sourceItemID))
|
||||
continue;
|
||||
|
||||
|
@ -183,10 +196,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
if ((dis < 10) && (dis > -10))
|
||||
{
|
||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||
sourceItemID, sPart.UUID, channel, name, msg
|
||||
);
|
||||
if (isListener != null)
|
||||
lock (CommListLock)
|
||||
{
|
||||
m_pending.Enqueue(isListener);
|
||||
}
|
||||
|
@ -197,10 +207,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
if ((dis < 30) && (dis > -30))
|
||||
{
|
||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||
sourceItemID, sPart.UUID, channel, name, msg
|
||||
);
|
||||
if (isListener != null)
|
||||
lock (CommListLock)
|
||||
{
|
||||
m_pending.Enqueue(isListener);
|
||||
}
|
||||
|
@ -210,10 +217,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
case ChatTypeEnum.Shout:
|
||||
if ((dis < 100) && (dis > -100))
|
||||
{
|
||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||
sourceItemID, sPart.UUID, channel, name, msg
|
||||
);
|
||||
if (isListener != null)
|
||||
lock (CommListLock)
|
||||
{
|
||||
m_pending.Enqueue(isListener);
|
||||
}
|
||||
|
@ -222,13 +226,15 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
case ChatTypeEnum.Broadcast:
|
||||
ListenerInfo isListen =
|
||||
m_listenerManager.IsListenerMatch(sourceItemID, eb, channel, name, msg);
|
||||
m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg);
|
||||
if (isListen != null)
|
||||
{
|
||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||
sourceItemID, sPart.UUID, channel, name, msg
|
||||
);
|
||||
if (isListener != null)
|
||||
{
|
||||
lock (CommListLock)
|
||||
{
|
||||
m_pending.Enqueue(isListener);
|
||||
}
|
||||
|
@ -242,7 +248,10 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public bool HasMessages()
|
||||
{
|
||||
if (m_pending != null)
|
||||
return (m_pending.Count > 0);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public ListenerInfo GetNextMessage()
|
||||
|
@ -256,6 +265,17 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
return li;
|
||||
}
|
||||
|
||||
public uint PeekNextMessageLocalID()
|
||||
{
|
||||
return m_pending.Peek().GetLocalID();
|
||||
}
|
||||
|
||||
public LLUUID PeekNextMessageItemID()
|
||||
{
|
||||
return m_pending.Peek().GetItemID();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// hostID: the ID of the ScenePart
|
||||
|
@ -272,8 +292,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_listeners = new Dictionary<int, ListenerInfo>();
|
||||
}
|
||||
|
||||
public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id,
|
||||
string msg)
|
||||
public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
|
||||
{
|
||||
if (m_listeners.Count < m_MaxListeners)
|
||||
{
|
||||
|
@ -305,6 +324,18 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_listeners.Remove(handle);
|
||||
}
|
||||
|
||||
public void DeleteListener(LLUUID itemID)
|
||||
{
|
||||
foreach (ListenerInfo li in m_listeners.Values)
|
||||
{
|
||||
if (li.GetItemID().Equals(itemID))
|
||||
{
|
||||
Remove(li.GetHandle());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int GetNewHandle()
|
||||
{
|
||||
for (int i = 0; i < int.MaxValue - 1; i++)
|
||||
|
@ -390,6 +421,11 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<int, ListenerInfo>.ValueCollection GetListeners()
|
||||
{
|
||||
return m_listeners.Values;
|
||||
}
|
||||
}
|
||||
|
||||
public class ListenerInfo
|
||||
|
@ -405,8 +441,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
private string m_message; // The message
|
||||
private bool m_active; // Listener is active or not
|
||||
|
||||
public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id,
|
||||
string message)
|
||||
public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
|
||||
{
|
||||
Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
|
||||
}
|
||||
|
@ -491,5 +526,6 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -75,26 +75,23 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
public class XMLRPCModule : IRegionModule, IXMLRPC
|
||||
{
|
||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
private Queue<RPCRequestInfo> rpcQueue = new Queue<RPCRequestInfo>();
|
||||
private object XMLRPCListLock = new object();
|
||||
private string m_name = "XMLRPCModule";
|
||||
private int RemoteReplyScriptWait = 300;
|
||||
private int RemoteReplyScriptTimeout = 900;
|
||||
private int RemoteReplyScriptTimeout = 9000;
|
||||
private int m_remoteDataPort = 0;
|
||||
private List<Scene> m_scenes = new List<Scene>();
|
||||
private LogBase m_log;
|
||||
|
||||
// <channel id, RPCChannelInfo>
|
||||
private Dictionary<LLUUID, RPCChannelInfo> m_openChannels;
|
||||
|
||||
// <channel id, RPCRequestInfo>
|
||||
private Dictionary<LLUUID, RPCRequestInfo> m_pendingResponse;
|
||||
private Dictionary<LLUUID, RPCRequestInfo> m_rpcPending;
|
||||
private Dictionary<LLUUID, RPCRequestInfo> m_rpcPendingResponses;
|
||||
|
||||
public XMLRPCModule()
|
||||
{
|
||||
m_log = MainLog.Instance;
|
||||
}
|
||||
private Dictionary<LLUUID, SendRemoteDataRequest> m_pendingSRDResponses;
|
||||
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
{
|
||||
|
@ -119,13 +116,15 @@ namespace OpenSim.Region.Environment.Modules
|
|||
if (IsEnabled())
|
||||
{
|
||||
m_openChannels = new Dictionary<LLUUID, RPCChannelInfo>();
|
||||
m_pendingResponse = new Dictionary<LLUUID, RPCRequestInfo>();
|
||||
m_rpcPending = new Dictionary<LLUUID, RPCRequestInfo>();
|
||||
m_rpcPendingResponses = new Dictionary<LLUUID, RPCRequestInfo>();
|
||||
m_pendingSRDResponses = new Dictionary<LLUUID, SendRemoteDataRequest>();
|
||||
|
||||
// Start http server
|
||||
// Attach xmlrpc handlers
|
||||
m_log.Verbose("REMOTE_DATA",
|
||||
m_log.Info("[REMOTE_DATA]: " +
|
||||
"Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands.");
|
||||
BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort);
|
||||
BaseHttpServer httpServer = new BaseHttpServer((uint)m_remoteDataPort);
|
||||
httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
|
||||
httpServer.Start();
|
||||
}
|
||||
|
@ -192,6 +191,34 @@ namespace OpenSim.Region.Environment.Modules
|
|||
return channel;
|
||||
}
|
||||
|
||||
// Delete channels based on itemID
|
||||
// for when a script is deleted
|
||||
public void DeleteChannels(LLUUID itemID)
|
||||
{
|
||||
|
||||
if (m_openChannels != null)
|
||||
{
|
||||
ArrayList tmp = new ArrayList();
|
||||
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
foreach (RPCChannelInfo li in m_openChannels.Values)
|
||||
{
|
||||
if (li.GetItemID().Equals(itemID))
|
||||
{
|
||||
tmp.Add(itemID);
|
||||
}
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator tmpEnumerator = tmp.GetEnumerator();
|
||||
while ( tmpEnumerator.MoveNext() )
|
||||
m_openChannels.Remove((LLUUID)tmpEnumerator.Current);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Remote Data Reply
|
||||
*
|
||||
|
@ -204,15 +231,12 @@ namespace OpenSim.Region.Environment.Modules
|
|||
RPCRequestInfo rpcInfo;
|
||||
LLUUID message_key = new LLUUID(message_id);
|
||||
|
||||
if (m_pendingResponse.TryGetValue(message_key, out rpcInfo))
|
||||
if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo))
|
||||
{
|
||||
rpcInfo.SetRetval(sdata);
|
||||
rpcInfo.SetStrRetval(sdata);
|
||||
rpcInfo.SetIntRetval(idata);
|
||||
rpcInfo.SetProcessed(true);
|
||||
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
m_pendingResponse.Remove(message_key);
|
||||
}
|
||||
m_rpcPendingResponses.Remove(message_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,18 +258,18 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
|
||||
Hashtable requestData = (Hashtable) request.Params[0];
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") &&
|
||||
requestData.Contains("StringValue"));
|
||||
|
||||
if (GoodXML)
|
||||
{
|
||||
LLUUID channel = new LLUUID((string) requestData["Channel"]);
|
||||
LLUUID channel = new LLUUID((string)requestData["Channel"]);
|
||||
RPCChannelInfo rpcChanInfo;
|
||||
if (m_openChannels.TryGetValue(channel, out rpcChanInfo))
|
||||
{
|
||||
string intVal = (string) requestData["IntValue"];
|
||||
string strVal = (string) requestData["StringValue"];
|
||||
string intVal = (string)requestData["IntValue"];
|
||||
string strVal = (string)requestData["StringValue"];
|
||||
|
||||
RPCRequestInfo rpcInfo;
|
||||
|
||||
|
@ -254,7 +278,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
rpcInfo =
|
||||
new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal,
|
||||
intVal);
|
||||
rpcQueue.Enqueue(rpcInfo);
|
||||
m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo);
|
||||
}
|
||||
|
||||
int timeoutCtr = 0;
|
||||
|
@ -266,16 +290,20 @@ namespace OpenSim.Region.Environment.Modules
|
|||
}
|
||||
if (rpcInfo.IsProcessed())
|
||||
{
|
||||
response.Value = rpcInfo.GetRetval();
|
||||
Hashtable param = new Hashtable();
|
||||
param["StringValue"] = rpcInfo.GetStrRetval();
|
||||
param["IntValue"] = Convert.ToString(rpcInfo.GetIntRetval());
|
||||
|
||||
ArrayList parameters = new ArrayList();
|
||||
parameters.Add(param);
|
||||
|
||||
response.Value = parameters;
|
||||
rpcInfo = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
response.SetFault(-1, "Script timeout");
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
m_pendingResponse.Remove(rpcInfo.GetMessageID());
|
||||
}
|
||||
rpcInfo = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -289,20 +317,112 @@ namespace OpenSim.Region.Environment.Modules
|
|||
|
||||
public bool hasRequests()
|
||||
{
|
||||
return (rpcQueue.Count > 0);
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
if (m_rpcPending != null)
|
||||
return (m_rpcPending.Count > 0);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public RPCRequestInfo GetNextRequest()
|
||||
public RPCRequestInfo GetNextCompletedRequest()
|
||||
{
|
||||
if (m_rpcPending != null)
|
||||
{
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
RPCRequestInfo rpcInfo = rpcQueue.Dequeue();
|
||||
m_pendingResponse.Add(rpcInfo.GetMessageID(), rpcInfo);
|
||||
return rpcInfo;
|
||||
foreach (LLUUID luid in m_rpcPending.Keys)
|
||||
{
|
||||
RPCRequestInfo tmpReq;
|
||||
|
||||
if (m_rpcPending.TryGetValue(luid, out tmpReq))
|
||||
{
|
||||
|
||||
if (!tmpReq.IsProcessed()) return tmpReq;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveCompletedRequest(LLUUID id)
|
||||
{
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
RPCRequestInfo tmp;
|
||||
if (m_rpcPending.TryGetValue(id, out tmp))
|
||||
{
|
||||
m_rpcPending.Remove(id);
|
||||
m_rpcPendingResponses.Add(id, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LLUUID SendRemoteData(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata)
|
||||
{
|
||||
|
||||
SendRemoteDataRequest req = new SendRemoteDataRequest(
|
||||
localID, itemID, channel, dest, idata, sdata
|
||||
);
|
||||
m_pendingSRDResponses.Add(req.GetReqID(), req);
|
||||
return req.process();
|
||||
|
||||
}
|
||||
|
||||
public SendRemoteDataRequest GetNextCompletedSRDRequest()
|
||||
{
|
||||
if (m_pendingSRDResponses != null)
|
||||
{
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
foreach (LLUUID luid in m_pendingSRDResponses.Keys)
|
||||
{
|
||||
SendRemoteDataRequest tmpReq;
|
||||
|
||||
if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq))
|
||||
{
|
||||
if (tmpReq.finished)
|
||||
return tmpReq;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveCompletedSRDRequest(LLUUID id)
|
||||
{
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
SendRemoteDataRequest tmpReq;
|
||||
if (m_pendingSRDResponses.TryGetValue(id, out tmpReq))
|
||||
{
|
||||
m_pendingSRDResponses.Remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelSRDRequests(LLUUID itemID)
|
||||
{
|
||||
if (m_pendingSRDResponses != null)
|
||||
{
|
||||
lock (XMLRPCListLock)
|
||||
{
|
||||
foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values)
|
||||
{
|
||||
if (li.m_itemID.Equals(itemID))
|
||||
m_pendingSRDResponses.Remove(li.GetReqID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**************************************************************
|
||||
*
|
||||
* Class RPCRequestInfo
|
||||
|
@ -316,7 +436,8 @@ namespace OpenSim.Region.Environment.Modules
|
|||
private string m_StrVal;
|
||||
private string m_IntVal;
|
||||
private bool m_processed;
|
||||
private string m_resp;
|
||||
private string m_respStr;
|
||||
private int m_respInt;
|
||||
private uint m_localID;
|
||||
private LLUUID m_ItemID;
|
||||
private LLUUID m_MessageID;
|
||||
|
@ -331,7 +452,8 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_ChannelKey = channelKey;
|
||||
m_MessageID = LLUUID.Random();
|
||||
m_processed = false;
|
||||
m_resp = "";
|
||||
m_respStr = String.Empty;
|
||||
m_respInt = 0;
|
||||
}
|
||||
|
||||
public bool IsProcessed()
|
||||
|
@ -349,16 +471,24 @@ namespace OpenSim.Region.Environment.Modules
|
|||
m_processed = processed;
|
||||
}
|
||||
|
||||
public void SetRetval(string resp)
|
||||
public void SetStrRetval(string resp)
|
||||
{
|
||||
m_resp = resp;
|
||||
m_respStr = resp;
|
||||
}
|
||||
|
||||
public string GetRetval()
|
||||
public string GetStrRetval()
|
||||
{
|
||||
return m_resp;
|
||||
return m_respStr;
|
||||
}
|
||||
public void SetIntRetval(int resp)
|
||||
{
|
||||
m_respInt = resp;
|
||||
}
|
||||
|
||||
public int GetIntRetval()
|
||||
{
|
||||
return m_respInt;
|
||||
}
|
||||
public uint GetLocalID()
|
||||
{
|
||||
return m_localID;
|
||||
|
@ -412,5 +542,141 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
return m_localID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SendRemoteDataRequest
|
||||
{
|
||||
|
||||
public LLUUID reqID;
|
||||
public string destURL;
|
||||
public string channel;
|
||||
public string sdata;
|
||||
public int idata;
|
||||
public bool finished;
|
||||
public string response_sdata;
|
||||
public int response_idata;
|
||||
public XmlRpcRequest request;
|
||||
private Thread httpThread;
|
||||
public LLUUID m_itemID;
|
||||
public uint m_localID;
|
||||
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata)
|
||||
{
|
||||
|
||||
this.channel = channel;
|
||||
this.destURL = dest;
|
||||
this.idata = idata;
|
||||
this.sdata = sdata;
|
||||
m_itemID = itemID;
|
||||
m_localID = localID;
|
||||
|
||||
reqID = LLUUID.Random();
|
||||
|
||||
}
|
||||
|
||||
public LLUUID process()
|
||||
{
|
||||
httpThread = new Thread(SendRequest);
|
||||
httpThread.Name = "HttpRequestThread";
|
||||
httpThread.Priority = ThreadPriority.BelowNormal;
|
||||
httpThread.IsBackground = true;
|
||||
finished = false;
|
||||
httpThread.Start();
|
||||
OpenSim.Framework.ThreadTracker.Add(httpThread);
|
||||
|
||||
return reqID;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: More work on the response codes. Right now
|
||||
* returning 200 for success or 499 for exception
|
||||
*/
|
||||
|
||||
public void SendRequest()
|
||||
{
|
||||
|
||||
Hashtable param = new Hashtable();
|
||||
|
||||
// Check if channel is an LLUUID
|
||||
// if not, use as method name
|
||||
LLUUID parseUID;
|
||||
string mName = "llRemoteData";
|
||||
if( (channel != null) && (channel != "") )
|
||||
if( !LLUUID.TryParse(channel, out parseUID) )
|
||||
mName = channel;
|
||||
else
|
||||
param["Channel"] = channel;
|
||||
|
||||
param["StringValue"] = sdata;
|
||||
param["IntValue"] = Convert.ToString(idata);
|
||||
|
||||
ArrayList parameters = new ArrayList();
|
||||
parameters.Add(param);
|
||||
XmlRpcRequest req = new XmlRpcRequest(mName, parameters);
|
||||
try
|
||||
{
|
||||
XmlRpcResponse resp = req.Send(destURL, 30000);
|
||||
if (resp != null)
|
||||
{
|
||||
Hashtable respParms;
|
||||
if(resp.Value.GetType().Equals(Type.GetType("System.Collections.Hashtable"))) {
|
||||
respParms = (Hashtable)resp.Value;
|
||||
}
|
||||
else {
|
||||
ArrayList respData = (ArrayList)resp.Value;
|
||||
respParms = (Hashtable)respData[0];
|
||||
}
|
||||
if (respParms != null)
|
||||
{
|
||||
if (respParms.Contains("StringValue"))
|
||||
{
|
||||
sdata = (string)respParms["StringValue"];
|
||||
}
|
||||
if (respParms.Contains("IntValue"))
|
||||
{
|
||||
idata = Convert.ToInt32((string)respParms["IntValue"]);
|
||||
}
|
||||
if (respParms.Contains("faultString"))
|
||||
{
|
||||
sdata = (string)respParms["faultString"];
|
||||
}
|
||||
if (respParms.Contains("faultCode"))
|
||||
{
|
||||
idata = Convert.ToInt32(respParms["faultCode"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Net.WebException we)
|
||||
{
|
||||
sdata = we.Message;
|
||||
m_log.Warn("[SendRemoteDataRequest]: Request failed");
|
||||
m_log.Warn(we.StackTrace);
|
||||
}
|
||||
|
||||
finished = true;
|
||||
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
httpThread.Abort();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public LLUUID GetReqID()
|
||||
{
|
||||
return reqID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* names of its contributors may be used to endorse or promote products
|
||||
* 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
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
|
@ -97,7 +97,11 @@ namespace OpenSim.Region.Environment.Modules
|
|||
XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
|
||||
Transfers.Add(xferID, transaction);
|
||||
NewFiles.Remove(fileName);
|
||||
transaction.StartSend();
|
||||
|
||||
if (transaction.StartSend())
|
||||
{
|
||||
Transfers.Remove(xferID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +111,12 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
if (Transfers.ContainsKey(xferID))
|
||||
{
|
||||
Transfers[xferID].AckPacket(packet);
|
||||
if (Transfers[xferID].AckPacket(packet))
|
||||
{
|
||||
{
|
||||
Transfers.Remove(xferID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,13 +140,13 @@ namespace OpenSim.Region.Environment.Modules
|
|||
public class XferDownLoad
|
||||
{
|
||||
public byte[] Data = new byte[0];
|
||||
public string FileName = "";
|
||||
public string FileName = String.Empty;
|
||||
public ulong XferID = 0;
|
||||
public int DataPointer = 0;
|
||||
public uint Packet = 0;
|
||||
public IClientAPI Client;
|
||||
public uint Serial = 1;
|
||||
private bool complete = false;
|
||||
private bool complete;
|
||||
|
||||
public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
|
||||
{
|
||||
|
@ -151,7 +160,11 @@ namespace OpenSim.Region.Environment.Modules
|
|||
{
|
||||
}
|
||||
|
||||
public void StartSend()
|
||||
/// <summary>
|
||||
/// Start a transfer
|
||||
/// </summary>
|
||||
/// <returns>True if the transfer is complete, false if not</returns>
|
||||
public bool StartSend()
|
||||
{
|
||||
if (Data.Length < 1000)
|
||||
{
|
||||
|
@ -160,6 +173,7 @@ namespace OpenSim.Region.Environment.Modules
|
|||
Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
|
||||
Array.Copy(Data, 0, transferData, 4, Data.Length);
|
||||
Client.SendXferPacket(XferID, 0 + 0x80000000, transferData);
|
||||
|
||||
complete = true;
|
||||
}
|
||||
else
|
||||
|
@ -171,9 +185,16 @@ namespace OpenSim.Region.Environment.Modules
|
|||
Packet++;
|
||||
DataPointer = 1000;
|
||||
}
|
||||
|
||||
return complete;
|
||||
}
|
||||
|
||||
public void AckPacket(uint packet)
|
||||
/// <summary>
|
||||
/// Respond to an ack packet from the client
|
||||
/// </summary>
|
||||
/// <param name="packet"></param>
|
||||
/// <returns>True if the transfer is complete, false otherwise</returns>
|
||||
public bool AckPacket(uint packet)
|
||||
{
|
||||
if (!complete)
|
||||
{
|
||||
|
@ -193,9 +214,12 @@ namespace OpenSim.Region.Environment.Modules
|
|||
Client.SendXferPacket(XferID, endPacket, transferData);
|
||||
Packet++;
|
||||
DataPointer += (Data.Length - DataPointer);
|
||||
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
return complete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue