* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,72 +1,72 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class AssetDownloadModule : IRegionModule
|
public class AssetDownloadModule : IRegionModule
|
||||||
{
|
{
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
|
||||||
public AssetDownloadModule()
|
public AssetDownloadModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_scene.EventManager.OnNewClient += NewClient;
|
m_scene.EventManager.OnNewClient += NewClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "AssetDownloadModule"; }
|
get { return "AssetDownloadModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NewClient(IClientAPI client)
|
public void NewClient(IClientAPI client)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,162 +1,339 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using libsecondlife;
|
using System.Threading;
|
||||||
using Nini.Config;
|
using libsecondlife;
|
||||||
using OpenSim.Framework;
|
using Nini.Config;
|
||||||
using OpenSim.Framework.Communications.Cache;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Communications.Cache;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
using OpenSim.Region.Environment.Scenes;
|
||||||
namespace OpenSim.Region.Environment.Modules
|
using OpenSim.Framework.Data;
|
||||||
{
|
using TribalMedia.Framework.Data;
|
||||||
public class AvatarFactoryModule : IAvatarFactory
|
|
||||||
{
|
namespace OpenSim.Region.Environment.Modules
|
||||||
private Scene m_scene = null;
|
{
|
||||||
private Dictionary<LLUUID, AvatarAppearance> m_avatarsAppearance = new Dictionary<LLUUID, AvatarAppearance>();
|
public class AvatarFactoryModule : IAvatarFactory
|
||||||
|
{
|
||||||
public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
|
private Scene m_scene = null;
|
||||||
{
|
private readonly Dictionary<LLUUID, AvatarAppearance> m_avatarsAppearance = new Dictionary<LLUUID, AvatarAppearance>();
|
||||||
if (m_avatarsAppearance.ContainsKey(avatarId))
|
|
||||||
{
|
private bool m_enablePersist = false;
|
||||||
appearance = m_avatarsAppearance[avatarId];
|
private string m_connectionString;
|
||||||
return true;
|
private bool m_configured = false;
|
||||||
}
|
private BaseDatabaseConnector m_databaseMapper;
|
||||||
else
|
private AppearanceTableMapper m_appearanceMapper;
|
||||||
{
|
|
||||||
AvatarWearable[] wearables;
|
private Dictionary<LLUUID, EventWaitHandle> m_fetchesInProgress = new Dictionary<LLUUID, EventWaitHandle>();
|
||||||
byte[] visualParams;
|
private object m_syncLock = new object();
|
||||||
GetDefaultAvatarAppearance(out wearables, out visualParams);
|
|
||||||
appearance = new AvatarAppearance(avatarId, wearables, visualParams);
|
public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance)
|
||||||
try
|
{
|
||||||
{
|
|
||||||
m_avatarsAppearance[avatarId] = appearance;
|
//should only let one thread at a time do this part
|
||||||
}
|
EventWaitHandle waitHandle = null;
|
||||||
catch (NullReferenceException)
|
bool fetchInProgress = false;
|
||||||
{
|
lock (m_syncLock)
|
||||||
MainLog.Instance.Error("AVATAR", "Unable to load appearance for uninitialized avatar");
|
{
|
||||||
}
|
appearance = CheckCache(avatarId);
|
||||||
return true;
|
if (appearance != null)
|
||||||
}
|
{
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
public void Initialise(Scene scene, IConfigSource source)
|
|
||||||
{
|
//not in cache so check to see if another thread is already fetching it
|
||||||
scene.RegisterModuleInterface<IAvatarFactory>(this);
|
if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle))
|
||||||
scene.EventManager.OnNewClient += NewClient;
|
{
|
||||||
|
fetchInProgress = true;
|
||||||
if (m_scene == null)
|
}
|
||||||
{
|
else
|
||||||
m_scene = scene;
|
{
|
||||||
}
|
fetchInProgress = false;
|
||||||
}
|
|
||||||
|
//no thread already fetching this appearance, so add a wait handle to list
|
||||||
public void PostInitialise()
|
//for any following threads that want the same appearance
|
||||||
{
|
waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
|
||||||
}
|
m_fetchesInProgress.Add(avatarId, waitHandle);
|
||||||
|
}
|
||||||
public void Close()
|
}
|
||||||
{
|
|
||||||
}
|
if (fetchInProgress)
|
||||||
|
{
|
||||||
public string Name
|
waitHandle.WaitOne();
|
||||||
{
|
appearance = CheckCache(avatarId);
|
||||||
get { return "Default Avatar Factory"; }
|
if (appearance != null)
|
||||||
}
|
{
|
||||||
|
waitHandle = null;
|
||||||
public bool IsSharedModule
|
return true;
|
||||||
{
|
}
|
||||||
get { return true; }
|
else
|
||||||
}
|
{
|
||||||
|
waitHandle = null;
|
||||||
public void NewClient(IClientAPI client)
|
return false;
|
||||||
{
|
}
|
||||||
client.OnAvatarNowWearing += AvatarIsWearing;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
public void RemoveClient(IClientAPI client)
|
Thread.Sleep(5000);
|
||||||
{
|
|
||||||
// client.OnAvatarNowWearing -= AvatarIsWearing;
|
//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
|
||||||
public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
|
appearance = CheckDatabase(avatarId);
|
||||||
{
|
if (appearance != null)
|
||||||
IClientAPI clientView = (IClientAPI) sender;
|
{
|
||||||
CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
|
//appearance has now been added to cache so lets pulse any waiting threads
|
||||||
if (profile != null)
|
lock (m_syncLock)
|
||||||
{
|
{
|
||||||
if (profile.RootFolder != null)
|
m_fetchesInProgress.Remove(avatarId);
|
||||||
{
|
waitHandle.Set();
|
||||||
//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
|
// waitHandle.Close();
|
||||||
foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
|
waitHandle = null;
|
||||||
{
|
return true;
|
||||||
if (wear.Type < 13)
|
}
|
||||||
{
|
|
||||||
LLUUID assetId;
|
//not found a appearance for the user, so create a new default one
|
||||||
|
appearance = CreateDefault(avatarId);
|
||||||
InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID);
|
if (appearance != null)
|
||||||
if (baseItem != null)
|
{
|
||||||
{
|
//update database
|
||||||
assetId = baseItem.assetID;
|
if (m_enablePersist)
|
||||||
//temporary dictionary storage. This should be storing to a database
|
{
|
||||||
|
m_appearanceMapper.Add(avatarId.UUID, appearance);
|
||||||
if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
|
}
|
||||||
{
|
|
||||||
AvatarAppearance avatAppearance = m_avatarsAppearance[clientView.AgentId];
|
//add appearance to dictionary cache
|
||||||
avatAppearance.Wearables[wear.Type].AssetID = assetId;
|
lock (m_avatarsAppearance)
|
||||||
avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
|
{
|
||||||
}
|
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();
|
||||||
public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
|
}
|
||||||
{
|
// waitHandle.Close();
|
||||||
visualParams = GetDefaultVisualParams();
|
waitHandle = null;
|
||||||
wearables = AvatarWearable.DefaultWearables;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
private static byte[] GetDefaultVisualParams()
|
{
|
||||||
{
|
//something went wrong, so release the wait handle and remove it
|
||||||
byte[] visualParams;
|
//all waiting threads will fail to find cached appearance
|
||||||
visualParams = new byte[218];
|
//but its better for them to fail than wait for ever
|
||||||
for (int i = 0; i < 218; i++)
|
lock (m_syncLock)
|
||||||
{
|
{
|
||||||
visualParams[i] = 100;
|
m_fetchesInProgress.Remove(avatarId);
|
||||||
}
|
waitHandle.Set();
|
||||||
return visualParams;
|
}
|
||||||
}
|
//waitHandle.Close();
|
||||||
}
|
waitHandle = null;
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AvatarAppearance CreateDefault(LLUUID avatarId)
|
||||||
|
{
|
||||||
|
AvatarAppearance appearance = null;
|
||||||
|
AvatarWearable[] wearables;
|
||||||
|
byte[] visualParams;
|
||||||
|
GetDefaultAvatarAppearance(out wearables, out visualParams);
|
||||||
|
appearance = new AvatarAppearance(avatarId, wearables, visualParams);
|
||||||
|
|
||||||
|
return appearance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AvatarAppearance CheckDatabase(LLUUID avatarId)
|
||||||
|
{
|
||||||
|
AvatarAppearance appearance = null;
|
||||||
|
if (m_enablePersist)
|
||||||
|
{
|
||||||
|
if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance))
|
||||||
|
{
|
||||||
|
appearance.VisualParams = GetDefaultVisualParams();
|
||||||
|
appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry();
|
||||||
|
lock (m_avatarsAppearance)
|
||||||
|
{
|
||||||
|
m_avatarsAppearance[avatarId] = appearance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return appearance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AvatarAppearance CheckCache(LLUUID avatarId)
|
||||||
|
{
|
||||||
|
AvatarAppearance appearance = null;
|
||||||
|
lock (m_avatarsAppearance)
|
||||||
|
{
|
||||||
|
if (m_avatarsAppearance.ContainsKey(avatarId))
|
||||||
|
{
|
||||||
|
appearance = m_avatarsAppearance[avatarId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return appearance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialise(Scene scene, IConfigSource source)
|
||||||
|
{
|
||||||
|
scene.RegisterModuleInterface<IAvatarFactory>(this);
|
||||||
|
scene.EventManager.OnNewClient += NewClient;
|
||||||
|
|
||||||
|
if (m_scene == null)
|
||||||
|
{
|
||||||
|
m_scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_configured)
|
||||||
|
{
|
||||||
|
m_configured = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false);
|
||||||
|
m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", "");
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (m_enablePersist)
|
||||||
|
{
|
||||||
|
m_databaseMapper = new MySQLDatabaseMapper(m_connectionString);
|
||||||
|
m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Default Avatar Factory"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSharedModule
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
client.OnAvatarNowWearing += AvatarIsWearing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
// client.OnAvatarNowWearing -= AvatarIsWearing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AvatarIsWearing(Object sender, AvatarWearingArgs e)
|
||||||
|
{
|
||||||
|
IClientAPI clientView = (IClientAPI)sender;
|
||||||
|
CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId);
|
||||||
|
if (profile != null)
|
||||||
|
{
|
||||||
|
if (profile.RootFolder != null)
|
||||||
|
{
|
||||||
|
if (m_avatarsAppearance.ContainsKey(clientView.AgentId))
|
||||||
|
{
|
||||||
|
AvatarAppearance avatAppearance = null;
|
||||||
|
lock (m_avatarsAppearance)
|
||||||
|
{
|
||||||
|
avatAppearance = m_avatarsAppearance[clientView.AgentId];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
|
||||||
|
{
|
||||||
|
if (wear.Type < 13)
|
||||||
|
{
|
||||||
|
if (wear.ItemID == LLUUID.Zero)
|
||||||
|
{
|
||||||
|
avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero;
|
||||||
|
avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero;
|
||||||
|
|
||||||
|
UpdateDatabase(clientView.AgentId, avatAppearance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LLUUID assetId;
|
||||||
|
|
||||||
|
InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID);
|
||||||
|
if (baseItem != null)
|
||||||
|
{
|
||||||
|
assetId = baseItem.assetID;
|
||||||
|
avatAppearance.Wearables[wear.Type].AssetID = assetId;
|
||||||
|
avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID;
|
||||||
|
|
||||||
|
UpdateDatabase(clientView.AgentId, avatAppearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance)
|
||||||
|
{
|
||||||
|
if (m_enablePersist)
|
||||||
|
{
|
||||||
|
m_appearanceMapper.Update(userID.UUID, avatAppearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams)
|
||||||
|
{
|
||||||
|
visualParams = GetDefaultVisualParams();
|
||||||
|
wearables = AvatarWearable.DefaultWearables;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] GetDefaultVisualParams()
|
||||||
|
{
|
||||||
|
byte[] visualParams;
|
||||||
|
visualParams = new byte[218];
|
||||||
|
for (int i = 0; i < 218; i++)
|
||||||
|
{
|
||||||
|
visualParams[i] = 100;
|
||||||
|
}
|
||||||
|
return visualParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,94 +1,94 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class AvatarProfilesModule : IRegionModule
|
public class AvatarProfilesModule : IRegionModule
|
||||||
{
|
{
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
|
||||||
public AvatarProfilesModule()
|
public AvatarProfilesModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_scene.EventManager.OnNewClient += NewClient;
|
m_scene.EventManager.OnNewClient += NewClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "AvatarProfilesModule"; }
|
get { return "AvatarProfilesModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NewClient(IClientAPI client)
|
public void NewClient(IClientAPI client)
|
||||||
{
|
{
|
||||||
client.OnRequestAvatarProperties += RequestAvatarProperty;
|
client.OnRequestAvatarProperties += RequestAvatarProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveClient(IClientAPI client)
|
public void RemoveClient(IClientAPI client)
|
||||||
{
|
{
|
||||||
client.OnRequestAvatarProperties -= RequestAvatarProperty;
|
client.OnRequestAvatarProperties -= RequestAvatarProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="remoteClient"></param>
|
/// <param name="remoteClient"></param>
|
||||||
/// <param name="avatarID"></param>
|
/// <param name="avatarID"></param>
|
||||||
public void RequestAvatarProperty(IClientAPI remoteClient, LLUUID avatarID)
|
public void RequestAvatarProperty(IClientAPI remoteClient, LLUUID avatarID)
|
||||||
{
|
{
|
||||||
string about = "OpenSim crash test dummy";
|
string about = "OpenSim crash test dummy";
|
||||||
string bornOn = "Before now";
|
string bornOn = "Before now";
|
||||||
string flAbout = "First life? What is one of those? OpenSim is my life!";
|
string flAbout = "First life? What is one of those? OpenSim is my life!";
|
||||||
LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000");
|
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);
|
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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,190 +1,190 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
|
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
|
||||||
{
|
{
|
||||||
private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
|
private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
|
||||||
|
|
||||||
private Dictionary<string, IDynamicTextureRender> RenderPlugins =
|
private Dictionary<string, IDynamicTextureRender> RenderPlugins =
|
||||||
new Dictionary<string, IDynamicTextureRender>();
|
new Dictionary<string, IDynamicTextureRender>();
|
||||||
|
|
||||||
private Dictionary<LLUUID, DynamicTextureUpdater> Updaters = new Dictionary<LLUUID, DynamicTextureUpdater>();
|
private Dictionary<LLUUID, DynamicTextureUpdater> Updaters = new Dictionary<LLUUID, DynamicTextureUpdater>();
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
|
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
|
||||||
{
|
{
|
||||||
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
|
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
|
||||||
scene.RegisterModuleInterface<IDynamicTextureManager>(this);
|
scene.RegisterModuleInterface<IDynamicTextureManager>(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "DynamicTextureModule"; }
|
get { return "DynamicTextureModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterRender(string handleType, IDynamicTextureRender render)
|
public void RegisterRender(string handleType, IDynamicTextureRender render)
|
||||||
{
|
{
|
||||||
if (!RenderPlugins.ContainsKey(handleType))
|
if (!RenderPlugins.ContainsKey(handleType))
|
||||||
{
|
{
|
||||||
RenderPlugins.Add(handleType, render);
|
RenderPlugins.Add(handleType, render);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReturnData(LLUUID id, byte[] data)
|
public void ReturnData(LLUUID id, byte[] data)
|
||||||
{
|
{
|
||||||
if (Updaters.ContainsKey(id))
|
if (Updaters.ContainsKey(id))
|
||||||
{
|
{
|
||||||
DynamicTextureUpdater updater = Updaters[id];
|
DynamicTextureUpdater updater = Updaters[id];
|
||||||
if (RegisteredScenes.ContainsKey(updater.SimUUID))
|
if (RegisteredScenes.ContainsKey(updater.SimUUID))
|
||||||
{
|
{
|
||||||
Scene scene = RegisteredScenes[updater.SimUUID];
|
Scene scene = RegisteredScenes[updater.SimUUID];
|
||||||
updater.DataReceived(data, scene);
|
updater.DataReceived(data, scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url,
|
public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url,
|
||||||
string extraParams, int updateTimer)
|
string extraParams, int updateTimer)
|
||||||
{
|
{
|
||||||
if (RenderPlugins.ContainsKey(contentType))
|
if (RenderPlugins.ContainsKey(contentType))
|
||||||
{
|
{
|
||||||
//Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType);
|
//Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType);
|
||||||
|
|
||||||
DynamicTextureUpdater updater = new DynamicTextureUpdater();
|
DynamicTextureUpdater updater = new DynamicTextureUpdater();
|
||||||
updater.SimUUID = simID;
|
updater.SimUUID = simID;
|
||||||
updater.PrimID = primID;
|
updater.PrimID = primID;
|
||||||
updater.ContentType = contentType;
|
updater.ContentType = contentType;
|
||||||
updater.Url = url;
|
updater.Url = url;
|
||||||
updater.UpdateTimer = updateTimer;
|
updater.UpdateTimer = updateTimer;
|
||||||
updater.UpdaterID = LLUUID.Random();
|
updater.UpdaterID = LLUUID.Random();
|
||||||
updater.Params = extraParams;
|
updater.Params = extraParams;
|
||||||
|
|
||||||
if (!Updaters.ContainsKey(updater.UpdaterID))
|
if (!Updaters.ContainsKey(updater.UpdaterID))
|
||||||
{
|
{
|
||||||
Updaters.Add(updater.UpdaterID, updater);
|
Updaters.Add(updater.UpdaterID, updater);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
|
RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
|
||||||
return updater.UpdaterID;
|
return updater.UpdaterID;
|
||||||
}
|
}
|
||||||
return LLUUID.Zero;
|
return LLUUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data,
|
public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data,
|
||||||
string extraParams, int updateTimer)
|
string extraParams, int updateTimer)
|
||||||
{
|
{
|
||||||
if (RenderPlugins.ContainsKey(contentType))
|
if (RenderPlugins.ContainsKey(contentType))
|
||||||
{
|
{
|
||||||
DynamicTextureUpdater updater = new DynamicTextureUpdater();
|
DynamicTextureUpdater updater = new DynamicTextureUpdater();
|
||||||
updater.SimUUID = simID;
|
updater.SimUUID = simID;
|
||||||
updater.PrimID = primID;
|
updater.PrimID = primID;
|
||||||
updater.ContentType = contentType;
|
updater.ContentType = contentType;
|
||||||
updater.BodyData = data;
|
updater.BodyData = data;
|
||||||
updater.UpdateTimer = updateTimer;
|
updater.UpdateTimer = updateTimer;
|
||||||
updater.UpdaterID = LLUUID.Random();
|
updater.UpdaterID = LLUUID.Random();
|
||||||
updater.Params = extraParams;
|
updater.Params = extraParams;
|
||||||
|
|
||||||
if (!Updaters.ContainsKey(updater.UpdaterID))
|
if (!Updaters.ContainsKey(updater.UpdaterID))
|
||||||
{
|
{
|
||||||
Updaters.Add(updater.UpdaterID, updater);
|
Updaters.Add(updater.UpdaterID, updater);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
|
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
|
||||||
return updater.UpdaterID;
|
return updater.UpdaterID;
|
||||||
}
|
}
|
||||||
return LLUUID.Zero;
|
return LLUUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DynamicTextureUpdater
|
public class DynamicTextureUpdater
|
||||||
{
|
{
|
||||||
public LLUUID SimUUID;
|
public LLUUID SimUUID;
|
||||||
public LLUUID UpdaterID;
|
public LLUUID UpdaterID;
|
||||||
public string ContentType;
|
public string ContentType;
|
||||||
public string Url;
|
public string Url;
|
||||||
public string BodyData;
|
public string BodyData;
|
||||||
public LLUUID PrimID;
|
public LLUUID PrimID;
|
||||||
public int UpdateTimer;
|
public int UpdateTimer;
|
||||||
public LLUUID LastAssetID;
|
public LLUUID LastAssetID;
|
||||||
public string Params;
|
public string Params;
|
||||||
|
|
||||||
public DynamicTextureUpdater()
|
public DynamicTextureUpdater()
|
||||||
{
|
{
|
||||||
LastAssetID = LLUUID.Zero;
|
LastAssetID = LLUUID.Zero;
|
||||||
UpdateTimer = 0;
|
UpdateTimer = 0;
|
||||||
BodyData = null;
|
BodyData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DataReceived(byte[] data, Scene scene)
|
public void DataReceived(byte[] data, Scene scene)
|
||||||
{
|
{
|
||||||
//TODO delete the last asset(data), if it was a dynamic texture
|
//TODO delete the last asset(data), if it was a dynamic texture
|
||||||
byte[] assetData = new byte[data.Length];
|
byte[] assetData = new byte[data.Length];
|
||||||
Array.Copy(data, assetData, data.Length);
|
Array.Copy(data, assetData, data.Length);
|
||||||
AssetBase asset = new AssetBase();
|
AssetBase asset = new AssetBase();
|
||||||
asset.FullID = LLUUID.Random();
|
asset.FullID = LLUUID.Random();
|
||||||
asset.Data = assetData;
|
asset.Data = assetData;
|
||||||
asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000);
|
asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000);
|
||||||
asset.Type = 0;
|
asset.Type = 0;
|
||||||
asset.Description = "dynamic image";
|
asset.Description = "dynamic image";
|
||||||
asset.Local = false;
|
asset.Local = false;
|
||||||
asset.Temporary = false;
|
asset.Temporary = true;
|
||||||
scene.AssetCache.AddAsset(asset);
|
scene.AssetCache.AddAsset(asset);
|
||||||
|
|
||||||
LastAssetID = asset.FullID;
|
LastAssetID = asset.FullID;
|
||||||
|
|
||||||
SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
|
SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
|
||||||
part.Shape.Textures = new LLObject.TextureEntry(asset.FullID);
|
part.Shape.Textures = new LLObject.TextureEntry(asset.FullID);
|
||||||
part.ScheduleFullUpdate();
|
part.ScheduleFullUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
internal class EmailModule
|
internal class EmailModule
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,233 +1,222 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class FriendsModule : IRegionModule
|
public class FriendsModule : IRegionModule
|
||||||
{
|
{
|
||||||
|
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private LogBase m_log;
|
|
||||||
|
private Scene m_scene;
|
||||||
private Scene m_scene;
|
|
||||||
|
Dictionary<LLUUID, LLUUID> m_pendingFriendRequests = new Dictionary<LLUUID, LLUUID>();
|
||||||
Dictionary<LLUUID, LLUUID> m_pendingFriendRequests = new Dictionary<LLUUID, LLUUID>();
|
|
||||||
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
{
|
||||||
{
|
m_scene = scene;
|
||||||
m_log = MainLog.Instance;
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
m_scene = scene;
|
scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage;
|
||||||
scene.EventManager.OnNewClient += OnNewClient;
|
}
|
||||||
scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage;
|
|
||||||
}
|
private void OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
private void OnNewClient(IClientAPI client)
|
// All friends establishment protocol goes over instant message
|
||||||
{
|
// There's no way to send a message from the sim
|
||||||
// All friends establishment protocol goes over instant message
|
// to a user to 'add a friend' without causing dialog box spam
|
||||||
// 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
|
||||||
// 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;
|
||||||
// Subscribe to instant messages
|
client.OnApproveFriendRequest += OnApprovedFriendRequest;
|
||||||
client.OnInstantMessage += OnInstantMessage;
|
client.OnDenyFriendRequest += OnDenyFriendRequest;
|
||||||
client.OnApproveFriendRequest += OnApprovedFriendRequest;
|
client.OnTerminateFriendship += OnTerminateFriendship;
|
||||||
client.OnDenyFriendRequest += OnDenyFriendRequest;
|
|
||||||
client.OnTerminateFriendship += OnTerminateFriendship;
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID,
|
||||||
private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID,
|
LLUUID fromAgentSession, LLUUID toAgentID,
|
||||||
LLUUID fromAgentSession, LLUUID toAgentID,
|
LLUUID imSessionID, uint timestamp, string fromAgentName,
|
||||||
LLUUID imSessionID, uint timestamp, string fromAgentName,
|
string message, byte dialog, bool fromGroup, byte offline,
|
||||||
string message, byte dialog, bool fromGroup, byte offline,
|
uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
|
||||||
uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
|
byte[] binaryBucket)
|
||||||
byte[] binaryBucket)
|
{
|
||||||
{
|
// Friend Requests go by Instant Message.. using the dialog param
|
||||||
// Friend Requests go by Instant Message.. using the dialog param
|
// https://wiki.secondlife.com/wiki/ImprovedInstantMessage
|
||||||
// https://wiki.secondlife.com/wiki/ImprovedInstantMessage
|
|
||||||
|
// 38 == Offer friendship
|
||||||
// 38 == Offer friendship
|
if (dialog == (byte)38)
|
||||||
if (dialog == (byte)38)
|
{
|
||||||
{
|
LLUUID friendTransactionID = LLUUID.Random();
|
||||||
LLUUID friendTransactionID = LLUUID.Random();
|
|
||||||
|
m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
|
||||||
m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
|
|
||||||
|
m_log.Info("[FRIEND]: 38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||||
m_log.Verbose("FRIEND", "38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
GridInstantMessage msg = new GridInstantMessage();
|
||||||
GridInstantMessage msg = new GridInstantMessage();
|
msg.fromAgentID = fromAgentID.UUID;
|
||||||
msg.fromAgentID = fromAgentID.UUID;
|
msg.fromAgentSession = fromAgentSession.UUID;
|
||||||
msg.fromAgentSession = fromAgentSession.UUID;
|
msg.toAgentID = toAgentID.UUID;
|
||||||
msg.toAgentID = toAgentID.UUID;
|
msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here
|
||||||
msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here
|
m_log.Info("[FRIEND]: Filling Session: " + msg.imSessionID.ToString());
|
||||||
m_log.Verbose("FRIEND","Filling Session: " + msg.imSessionID.ToString());
|
msg.timestamp = timestamp;
|
||||||
msg.timestamp = timestamp;
|
if (client != null)
|
||||||
if (client != null)
|
{
|
||||||
{
|
msg.fromAgentName = client.FirstName + " " + client.LastName;// fromAgentName;
|
||||||
msg.fromAgentName = client.FirstName + " " + client.LastName;// fromAgentName;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
|
||||||
msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
|
}
|
||||||
}
|
msg.message = message;
|
||||||
msg.message = message;
|
msg.dialog = dialog;
|
||||||
msg.dialog = dialog;
|
msg.fromGroup = fromGroup;
|
||||||
msg.fromGroup = fromGroup;
|
msg.offline = offline;
|
||||||
msg.offline = offline;
|
msg.ParentEstateID = ParentEstateID;
|
||||||
msg.ParentEstateID = ParentEstateID;
|
msg.Position = new sLLVector3(Position);
|
||||||
msg.Position = new sLLVector3(Position);
|
msg.RegionID = RegionID.UUID;
|
||||||
msg.RegionID = RegionID.UUID;
|
msg.binaryBucket = binaryBucket;
|
||||||
msg.binaryBucket = binaryBucket;
|
m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
|
||||||
m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
|
}
|
||||||
}
|
|
||||||
if (dialog == (byte)39)
|
// 39 == Accept Friendship
|
||||||
{
|
if (dialog == (byte)39)
|
||||||
m_log.Verbose("FRIEND", "38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
{
|
||||||
|
m_log.Info("[FRIEND]: 39 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||||
}
|
}
|
||||||
if (dialog == (byte)40)
|
|
||||||
{
|
// 40 == Decline Friendship
|
||||||
m_log.Verbose("FRIEND", "38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
if (dialog == (byte)40)
|
||||||
}
|
{
|
||||||
|
m_log.Info("[FRIEND]: 40 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message);
|
||||||
// 39 == Accept Friendship
|
}
|
||||||
|
}
|
||||||
// 40 == Decline Friendship
|
|
||||||
|
private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List<LLUUID> callingCardFolders)
|
||||||
}
|
{
|
||||||
|
if (m_pendingFriendRequests.ContainsKey(transactionID))
|
||||||
private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List<LLUUID> callingCardFolders)
|
{
|
||||||
{
|
// Found Pending Friend Request with that Transaction..
|
||||||
if (m_pendingFriendRequests.ContainsKey(transactionID))
|
|
||||||
{
|
// Compose response to other agent.
|
||||||
// Found Pending Friend Request with that Transaction..
|
GridInstantMessage msg = new GridInstantMessage();
|
||||||
|
msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
|
||||||
// Compose response to other agent.
|
msg.fromAgentID = agentID.UUID;
|
||||||
GridInstantMessage msg = new GridInstantMessage();
|
msg.fromAgentName = client.FirstName + " " + client.LastName;
|
||||||
msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
|
msg.fromAgentSession = client.SessionId.UUID;
|
||||||
msg.fromAgentID = agentID.UUID;
|
msg.fromGroup = false;
|
||||||
msg.fromAgentName = client.FirstName + " " + client.LastName;
|
msg.imSessionID = transactionID.UUID;
|
||||||
msg.fromAgentSession = client.SessionId.UUID;
|
msg.message = agentID.UUID.ToString();
|
||||||
msg.fromGroup = false;
|
msg.ParentEstateID = 0;
|
||||||
msg.imSessionID = transactionID.UUID;
|
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
msg.message = agentID.UUID.ToString();
|
msg.RegionID = m_scene.RegionInfo.RegionID.UUID;
|
||||||
msg.ParentEstateID = 0;
|
msg.dialog = (byte)39;// Approved friend request
|
||||||
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
msg.Position = new sLLVector3();
|
||||||
msg.RegionID = m_scene.RegionInfo.RegionID.UUID;
|
msg.offline = (byte)0;
|
||||||
msg.dialog = (byte)39;// Approved friend request
|
msg.binaryBucket = new byte[0];
|
||||||
msg.Position = new sLLVector3();
|
m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
|
||||||
msg.offline = (byte)0;
|
m_scene.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint)1);
|
||||||
msg.binaryBucket = new byte[0];
|
m_pendingFriendRequests.Remove(transactionID);
|
||||||
m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
|
|
||||||
m_scene.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint)1);
|
// TODO: Inform agent that the friend is online
|
||||||
m_pendingFriendRequests.Remove(transactionID);
|
}
|
||||||
|
}
|
||||||
// TODO: Inform agent that the friend is online
|
|
||||||
}
|
private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List<LLUUID> callingCardFolders)
|
||||||
}
|
{
|
||||||
private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List<LLUUID> callingCardFolders)
|
if (m_pendingFriendRequests.ContainsKey(transactionID))
|
||||||
{
|
{
|
||||||
if (m_pendingFriendRequests.ContainsKey(transactionID))
|
// Found Pending Friend Request with that Transaction..
|
||||||
{
|
|
||||||
// Found Pending Friend Request with that Transaction..
|
// Compose response to other agent.
|
||||||
|
GridInstantMessage msg = new GridInstantMessage();
|
||||||
// Compose response to other agent.
|
msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
|
||||||
GridInstantMessage msg = new GridInstantMessage();
|
msg.fromAgentID = agentID.UUID;
|
||||||
msg.toAgentID = m_pendingFriendRequests[transactionID].UUID;
|
msg.fromAgentName = client.FirstName + " " + client.LastName;
|
||||||
msg.fromAgentID = agentID.UUID;
|
msg.fromAgentSession = client.SessionId.UUID;
|
||||||
msg.fromAgentName = client.FirstName + " " + client.LastName;
|
msg.fromGroup = false;
|
||||||
msg.fromAgentSession = client.SessionId.UUID;
|
msg.imSessionID = transactionID.UUID;
|
||||||
msg.fromGroup = false;
|
msg.message = agentID.UUID.ToString();
|
||||||
msg.imSessionID = transactionID.UUID;
|
msg.ParentEstateID = 0;
|
||||||
msg.message = agentID.UUID.ToString();
|
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
msg.ParentEstateID = 0;
|
msg.RegionID = m_scene.RegionInfo.RegionID.UUID;
|
||||||
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
msg.dialog = (byte)40;// Deny friend request
|
||||||
msg.RegionID = m_scene.RegionInfo.RegionID.UUID;
|
msg.Position = new sLLVector3();
|
||||||
msg.dialog = (byte)40;// Deny friend request
|
msg.offline = (byte)0;
|
||||||
msg.Position = new sLLVector3();
|
msg.binaryBucket = new byte[0];
|
||||||
msg.offline = (byte)0;
|
m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
|
||||||
msg.binaryBucket = new byte[0];
|
m_pendingFriendRequests.Remove(transactionID);
|
||||||
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 OnTerminateFriendship(IClientAPI client, LLUUID agent, LLUUID exfriendID)
|
|
||||||
{
|
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||||
m_scene.StoreRemoveFriendship(agent, exfriendID);
|
{
|
||||||
// TODO: Inform the client that the ExFriend is offline
|
// 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),
|
||||||
private void OnGridInstantMessage(GridInstantMessage msg)
|
msg.binaryBucket);
|
||||||
{
|
}
|
||||||
// Trigger the above event handler
|
|
||||||
OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
|
public void PostInitialise()
|
||||||
new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
|
{
|
||||||
msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
|
}
|
||||||
new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
|
|
||||||
msg.binaryBucket);
|
public void Close()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
public void PostInitialise()
|
{
|
||||||
{
|
get { return "FriendsModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsSharedModule
|
||||||
|
{
|
||||||
public void Close()
|
get { return false; }
|
||||||
{
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get { return "FriendsModule"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSharedModule
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,62 +1,279 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using System;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
namespace OpenSim.Region.Environment.Modules
|
using OpenSim.Framework;
|
||||||
{
|
using OpenSim.Framework.Console;
|
||||||
public class GroupsModule : IRegionModule
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
{
|
using OpenSim.Region.Environment.Scenes;
|
||||||
private Scene m_scene;
|
using libsecondlife;
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
public class GroupsModule : IRegionModule
|
||||||
}
|
{
|
||||||
|
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
public void PostInitialise()
|
|
||||||
{
|
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>();
|
||||||
public void Close()
|
private Dictionary<LLUUID, GroupList> m_grouplistmap = new Dictionary<LLUUID, GroupList>();
|
||||||
{
|
|
||||||
}
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
|
{
|
||||||
public string Name
|
lock (m_scene)
|
||||||
{
|
{
|
||||||
get { return "GroupsModule"; }
|
m_scene.Add(scene);
|
||||||
}
|
}
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
public bool IsSharedModule
|
scene.EventManager.OnClientClosed += OnClientClosed;
|
||||||
{
|
scene.EventManager.OnGridInstantMessageToGroupsModule += OnGridInstantMessage;
|
||||||
get { return false; }
|
//scene.EventManager.
|
||||||
}
|
}
|
||||||
}
|
private void OnNewClient(IClientAPI client)
|
||||||
}
|
{
|
||||||
|
// All friends establishment protocol goes over instant message
|
||||||
|
// There's no way to send a message from the sim
|
||||||
|
// to a user to 'add a friend' without causing dialog box spam
|
||||||
|
//
|
||||||
|
// The base set of friends are added when the user signs on in their XMLRPC response
|
||||||
|
// Generated by LoginService. The friends are retreived from the database by the UserManager
|
||||||
|
|
||||||
|
// Subscribe to instant messages
|
||||||
|
client.OnInstantMessage += OnInstantMessage;
|
||||||
|
client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
|
||||||
|
lock (m_iclientmap)
|
||||||
|
{
|
||||||
|
if (!m_iclientmap.ContainsKey(client.AgentId))
|
||||||
|
{
|
||||||
|
m_iclientmap.Add(client.AgentId, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GroupData OpenSimulatorGroup = new GroupData();
|
||||||
|
OpenSimulatorGroup.ActiveGroupTitle = "OpenSimulator Tester";
|
||||||
|
OpenSimulatorGroup.GroupID = new LLUUID("00000000-68f9-1111-024e-222222111120");
|
||||||
|
OpenSimulatorGroup.GroupMembers.Add(client.AgentId);
|
||||||
|
OpenSimulatorGroup.groupName = "OpenSimulator Testing";
|
||||||
|
OpenSimulatorGroup.ActiveGroupPowers = GroupPowers.LandAllowSetHome;
|
||||||
|
OpenSimulatorGroup.GroupTitles.Add("OpenSimulator Tester");
|
||||||
|
lock (m_groupmap)
|
||||||
|
{
|
||||||
|
if (!m_groupmap.ContainsKey(client.AgentId))
|
||||||
|
{
|
||||||
|
m_groupmap.Add(client.AgentId, OpenSimulatorGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GroupList testGroupList = new GroupList();
|
||||||
|
testGroupList.m_GroupList.Add(new LLUUID("00000000-68f9-1111-024e-222222111120"));
|
||||||
|
|
||||||
|
lock (m_grouplistmap)
|
||||||
|
{
|
||||||
|
if (!m_grouplistmap.ContainsKey(client.AgentId))
|
||||||
|
{
|
||||||
|
m_grouplistmap.Add(client.AgentId, testGroupList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_log.Info("[GROUP]: Adding " + client.FirstName + " " + client.LastName + " to OpenSimulator Tester group");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAgentDataUpdateRequest(IClientAPI remoteClient, LLUUID AgentID, LLUUID SessionID)
|
||||||
|
{
|
||||||
|
string firstname = remoteClient.FirstName;
|
||||||
|
string lastname = remoteClient.LastName;
|
||||||
|
|
||||||
|
LLUUID ActiveGroupID = LLUUID.Zero;
|
||||||
|
uint ActiveGroupPowers = 0;
|
||||||
|
string ActiveGroupName = "";
|
||||||
|
string ActiveGroupTitle = "";
|
||||||
|
|
||||||
|
bool foundUser = false;
|
||||||
|
|
||||||
|
lock (m_iclientmap)
|
||||||
|
{
|
||||||
|
if (m_iclientmap.ContainsKey(remoteClient.AgentId))
|
||||||
|
{
|
||||||
|
foundUser = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundUser)
|
||||||
|
{
|
||||||
|
lock (m_groupmap)
|
||||||
|
{
|
||||||
|
if (m_groupmap.ContainsKey(remoteClient.AgentId))
|
||||||
|
{
|
||||||
|
GroupData grp = m_groupmap[remoteClient.AgentId];
|
||||||
|
if (grp != null)
|
||||||
|
{
|
||||||
|
ActiveGroupID = grp.GroupID;
|
||||||
|
ActiveGroupName = grp.groupName;
|
||||||
|
ActiveGroupPowers = grp.groupPowers;
|
||||||
|
ActiveGroupTitle = grp.ActiveGroupTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
//remoteClient.SendAgentDataUpdate(AgentID, ActiveGroupID, firstname, lastname, ActiveGroupPowers, ActiveGroupName, ActiveGroupTitle);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInstantMessage(IClientAPI client, LLUUID fromAgentID,
|
||||||
|
LLUUID fromAgentSession, LLUUID toAgentID,
|
||||||
|
LLUUID imSessionID, uint timestamp, string fromAgentName,
|
||||||
|
string message, byte dialog, bool fromGroup, byte offline,
|
||||||
|
uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
|
||||||
|
byte[] binaryBucket)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||||
|
{
|
||||||
|
// Trigger the above event handler
|
||||||
|
OnInstantMessage(null, new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
|
||||||
|
new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
|
||||||
|
msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID,
|
||||||
|
new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID),
|
||||||
|
msg.binaryBucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnClientClosed(LLUUID agentID)
|
||||||
|
{
|
||||||
|
lock (m_iclientmap)
|
||||||
|
{
|
||||||
|
if (m_iclientmap.ContainsKey(agentID))
|
||||||
|
{
|
||||||
|
IClientAPI cli = m_iclientmap[agentID];
|
||||||
|
if (cli != null)
|
||||||
|
{
|
||||||
|
m_log.Info("[GROUP]: Removing all reference to groups for " + cli.FirstName + " " + cli.LastName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Info("[GROUP]: Removing all reference to groups for " + agentID.ToString());
|
||||||
|
}
|
||||||
|
m_iclientmap.Remove(agentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_groupmap)
|
||||||
|
{
|
||||||
|
if (m_groupmap.ContainsKey(agentID))
|
||||||
|
{
|
||||||
|
m_groupmap.Remove(agentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_grouplistmap)
|
||||||
|
{
|
||||||
|
if (m_grouplistmap.ContainsKey(agentID))
|
||||||
|
{
|
||||||
|
m_grouplistmap.Remove(agentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_log.Info("[GROUP]: Shutting down group module.");
|
||||||
|
lock (m_iclientmap)
|
||||||
|
{
|
||||||
|
m_iclientmap.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_groupmap)
|
||||||
|
{
|
||||||
|
m_groupmap.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_grouplistmap)
|
||||||
|
{
|
||||||
|
m_grouplistmap.Clear();
|
||||||
|
}
|
||||||
|
GC.Collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "GroupsModule"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSharedModule
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public class GroupData
|
||||||
|
{
|
||||||
|
public LLUUID GroupID;
|
||||||
|
public string groupName;
|
||||||
|
public string ActiveGroupTitle;
|
||||||
|
public List<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>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,134 +1,127 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class InstantMessageModule : IRegionModule
|
public class InstantMessageModule : IRegionModule
|
||||||
{
|
{
|
||||||
private List<Scene> m_scenes = new List<Scene>();
|
private List<Scene> m_scenes = new List<Scene>();
|
||||||
private LogBase m_log;
|
|
||||||
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
public InstantMessageModule()
|
{
|
||||||
{
|
if (!m_scenes.Contains(scene))
|
||||||
m_log = MainLog.Instance;
|
{
|
||||||
}
|
m_scenes.Add(scene);
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage;
|
||||||
{
|
}
|
||||||
if (!m_scenes.Contains(scene))
|
}
|
||||||
{
|
|
||||||
m_scenes.Add(scene);
|
private void OnNewClient(IClientAPI client)
|
||||||
scene.EventManager.OnNewClient += OnNewClient;
|
{
|
||||||
scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage;
|
client.OnInstantMessage += OnInstantMessage;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID,
|
||||||
private void OnNewClient(IClientAPI client)
|
LLUUID fromAgentSession, LLUUID toAgentID,
|
||||||
{
|
LLUUID imSessionID, uint timestamp, string fromAgentName,
|
||||||
client.OnInstantMessage += OnInstantMessage;
|
string message, byte dialog, bool fromGroup, byte offline,
|
||||||
}
|
uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
|
||||||
|
byte[] binaryBucket)
|
||||||
private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID,
|
{
|
||||||
LLUUID fromAgentSession, LLUUID toAgentID,
|
bool FriendDialog = ((dialog == (byte)38) || (dialog == (byte)39) || (dialog == (byte)40));
|
||||||
LLUUID imSessionID, uint timestamp, string fromAgentName,
|
|
||||||
string message, byte dialog, bool fromGroup, byte offline,
|
// IM dialogs need to be pre-processed and have their sessionID filled by the server
|
||||||
uint ParentEstateID, LLVector3 Position, LLUUID RegionID,
|
// so the sim can match the transaction on the return packet.
|
||||||
byte[] binaryBucket)
|
|
||||||
{
|
// Don't send a Friend Dialog IM with a LLUUID.Zero session.
|
||||||
|
if (!(FriendDialog && imSessionID == LLUUID.Zero))
|
||||||
bool FriendDialog = ((dialog == (byte)38) || (dialog == (byte)39) || (dialog == (byte)40));
|
{
|
||||||
|
foreach (Scene scene in m_scenes)
|
||||||
// IM dialogs need to be pre-processed and have their sessionID filled by the server
|
{
|
||||||
// so the sim can match the transaction on the return packet.
|
if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
|
||||||
|
{
|
||||||
// Don't send a Friend Dialog IM with a LLUUID.Zero session.
|
// Local message
|
||||||
if (!(FriendDialog && imSessionID == LLUUID.Zero))
|
ScenePresence user = (ScenePresence)scene.Entities[toAgentID];
|
||||||
{
|
if (!user.IsChildAgent)
|
||||||
foreach (Scene scene in m_scenes)
|
{
|
||||||
{
|
user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
|
||||||
if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence)
|
toAgentID, imSessionID, fromAgentName, dialog,
|
||||||
{
|
timestamp);
|
||||||
// Local message
|
// Message sent
|
||||||
ScenePresence user = (ScenePresence)scene.Entities[toAgentID];
|
return;
|
||||||
if (!user.IsChildAgent)
|
}
|
||||||
{
|
}
|
||||||
user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message,
|
}
|
||||||
toAgentID, imSessionID, fromAgentName, dialog,
|
}
|
||||||
timestamp);
|
|
||||||
// Message sent
|
// Still here, try send via Grid
|
||||||
return;
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// Trusty OSG1 called method. This method also gets called from the FriendsModule
|
||||||
}
|
// Turns out the sim has to send an instant message to the user to get it to show an accepted friend.
|
||||||
|
|
||||||
// Still here, try send via Grid
|
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||||
// TODO
|
{
|
||||||
}
|
// Trigger the above event handler
|
||||||
|
OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession),
|
||||||
// Trusty OSG1 called method. This method also gets called from the FriendsModule
|
new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName,
|
||||||
// Turns out the sim has to send an instant message to the user to get it to show an accepted friend.
|
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),
|
||||||
private void OnGridInstantMessage(GridInstantMessage msg)
|
msg.binaryBucket);
|
||||||
{
|
|
||||||
// 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,
|
public void PostInitialise()
|
||||||
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 Close()
|
||||||
}
|
{
|
||||||
|
}
|
||||||
public void PostInitialise()
|
|
||||||
{
|
public string Name
|
||||||
}
|
{
|
||||||
|
get { return "InstantMessageModule"; }
|
||||||
public void Close()
|
}
|
||||||
{
|
|
||||||
}
|
public bool IsSharedModule
|
||||||
|
{
|
||||||
public string Name
|
get { return true; }
|
||||||
{
|
}
|
||||||
get { return "InstantMessageModule"; }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,62 +1,62 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class InventoryModule : IRegionModule
|
public class InventoryModule : IRegionModule
|
||||||
{
|
{
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "InventoryModule"; }
|
get { return "InventoryModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,149 +1,177 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenJPEGNet;
|
using OpenJPEGNet;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class LoadImageURLModule : IRegionModule, IDynamicTextureRender
|
public class LoadImageURLModule : IRegionModule, IDynamicTextureRender
|
||||||
{
|
{
|
||||||
private string m_name = "LoadImageURL";
|
private string m_name = "LoadImageURL";
|
||||||
private IDynamicTextureManager m_textureManager;
|
private IDynamicTextureManager m_textureManager;
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
if (m_scene == null)
|
if (m_scene == null)
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
|
m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
|
||||||
m_textureManager.RegisterRender(GetContentType(), this);
|
m_textureManager.RegisterRender(GetContentType(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return m_name; }
|
get { return m_name; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetName()
|
public string GetName()
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetContentType()
|
public string GetContentType()
|
||||||
{
|
{
|
||||||
return ("image");
|
return ("image");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SupportsAsynchronous()
|
public bool SupportsAsynchronous()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ConvertUrl(string url, string extraParams)
|
public byte[] ConvertUrl(string url, string extraParams)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ConvertStream(Stream data, string extraParams)
|
public byte[] ConvertStream(Stream data, string extraParams)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AsyncConvertUrl(LLUUID id, string url, string extraParams)
|
public bool AsyncConvertUrl(LLUUID id, string url, string extraParams)
|
||||||
{
|
{
|
||||||
MakeHttpRequest(url, id);
|
MakeHttpRequest(url, id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams)
|
public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MakeHttpRequest(string url, LLUUID requestID)
|
private void MakeHttpRequest(string url, LLUUID requestID)
|
||||||
{
|
{
|
||||||
WebRequest request = HttpWebRequest.Create(url);
|
WebRequest request = HttpWebRequest.Create(url);
|
||||||
RequestState state = new RequestState((HttpWebRequest) request, requestID);
|
RequestState state = new RequestState((HttpWebRequest) request, requestID);
|
||||||
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
|
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
|
||||||
|
|
||||||
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
|
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
|
||||||
state.TimeOfRequest = (int) t.TotalSeconds;
|
state.TimeOfRequest = (int) t.TotalSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HttpRequestReturn(IAsyncResult result)
|
private void HttpRequestReturn(IAsyncResult result)
|
||||||
{
|
{
|
||||||
RequestState state = (RequestState) result.AsyncState;
|
RequestState state = (RequestState) result.AsyncState;
|
||||||
WebRequest request = (WebRequest) state.Request;
|
WebRequest request = (WebRequest) state.Request;
|
||||||
HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result);
|
HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result);
|
||||||
if (response.StatusCode == HttpStatusCode.OK)
|
if (response.StatusCode == HttpStatusCode.OK)
|
||||||
{
|
{
|
||||||
Bitmap image = new Bitmap(response.GetResponseStream());
|
Bitmap image = new Bitmap(response.GetResponseStream());
|
||||||
Bitmap resize = new Bitmap(image, new Size(512, 512));
|
Size newsize;
|
||||||
byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
|
|
||||||
|
// TODO: make this a bit less hard coded
|
||||||
m_textureManager.ReturnData(state.RequestID, imageJ2000);
|
if ((image.Height < 64) && (image.Width < 64))
|
||||||
}
|
{
|
||||||
}
|
newsize = new Size(32, 32);
|
||||||
|
}
|
||||||
public class RequestState
|
else if ((image.Height < 128) && (image.Width < 128))
|
||||||
{
|
{
|
||||||
public HttpWebRequest Request = null;
|
newsize = new Size(64, 64);
|
||||||
public LLUUID RequestID = LLUUID.Zero;
|
}
|
||||||
public int TimeOfRequest = 0;
|
else if ((image.Height <256) && (image.Width < 256))
|
||||||
|
{
|
||||||
public RequestState(HttpWebRequest request, LLUUID requestID)
|
newsize = new Size(128, 128);
|
||||||
{
|
}
|
||||||
Request = request;
|
else if ((image.Height < 512 && image.Width < 512))
|
||||||
RequestID = requestID;
|
{
|
||||||
}
|
newsize = new Size(256, 256);
|
||||||
}
|
}
|
||||||
}
|
else if ((image.Height < 1024 && image.Width < 1024))
|
||||||
}
|
{
|
||||||
|
newsize = new Size(512, 512);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newsize = new Size(1024,1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap resize = new Bitmap(image, newsize);
|
||||||
|
byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
|
||||||
|
|
||||||
|
m_textureManager.ReturnData(state.RequestID, imageJ2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RequestState
|
||||||
|
{
|
||||||
|
public HttpWebRequest Request = null;
|
||||||
|
public LLUUID RequestID = LLUUID.Zero;
|
||||||
|
public int TimeOfRequest = 0;
|
||||||
|
|
||||||
|
public RequestState(HttpWebRequest request, LLUUID requestID)
|
||||||
|
{
|
||||||
|
Request = request;
|
||||||
|
RequestID = requestID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,343 +1,361 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
/*****************************************************
|
/*****************************************************
|
||||||
*
|
*
|
||||||
* ScriptsHttpRequests
|
* ScriptsHttpRequests
|
||||||
*
|
*
|
||||||
* Implements the llHttpRequest and http_response
|
* Implements the llHttpRequest and http_response
|
||||||
* callback.
|
* callback.
|
||||||
*
|
*
|
||||||
* Some stuff was already in LSLLongCmdHandler, and then
|
* Some stuff was already in LSLLongCmdHandler, and then
|
||||||
* there was this file with a stub class in it. So,
|
* there was this file with a stub class in it. So,
|
||||||
* I am moving some of the objects and functions out of
|
* I am moving some of the objects and functions out of
|
||||||
* LSLLongCmdHandler, such as the HttpRequestClass, the
|
* LSLLongCmdHandler, such as the HttpRequestClass, the
|
||||||
* start and stop methods, and setting up pending and
|
* start and stop methods, and setting up pending and
|
||||||
* completed queues. These are processed in the
|
* completed queues. These are processed in the
|
||||||
* LSLLongCmdHandler polling loop. Similiar to the
|
* LSLLongCmdHandler polling loop. Similiar to the
|
||||||
* XMLRPCModule, since that seems to work.
|
* XMLRPCModule, since that seems to work.
|
||||||
*
|
*
|
||||||
* //TODO
|
* //TODO
|
||||||
*
|
*
|
||||||
* This probably needs some throttling mechanism but
|
* This probably needs some throttling mechanism but
|
||||||
* its wide open right now. This applies to both
|
* its wide open right now. This applies to both
|
||||||
* number of requests and data volume.
|
* number of requests and data volume.
|
||||||
*
|
*
|
||||||
* Linden puts all kinds of header fields in the requests.
|
* Linden puts all kinds of header fields in the requests.
|
||||||
* Not doing any of that:
|
* Not doing any of that:
|
||||||
* User-Agent
|
* User-Agent
|
||||||
* X-SecondLife-Shard
|
* X-SecondLife-Shard
|
||||||
* X-SecondLife-Object-Name
|
* X-SecondLife-Object-Name
|
||||||
* X-SecondLife-Object-Key
|
* X-SecondLife-Object-Key
|
||||||
* X-SecondLife-Region
|
* X-SecondLife-Region
|
||||||
* X-SecondLife-Local-Position
|
* X-SecondLife-Local-Position
|
||||||
* X-SecondLife-Local-Velocity
|
* X-SecondLife-Local-Velocity
|
||||||
* X-SecondLife-Local-Rotation
|
* X-SecondLife-Local-Rotation
|
||||||
* X-SecondLife-Owner-Name
|
* X-SecondLife-Owner-Name
|
||||||
* X-SecondLife-Owner-Key
|
* X-SecondLife-Owner-Key
|
||||||
*
|
*
|
||||||
* HTTPS support
|
* HTTPS support
|
||||||
*
|
*
|
||||||
* Configurable timeout?
|
* Configurable timeout?
|
||||||
* Configurable max repsonse size?
|
* Configurable max repsonse size?
|
||||||
* Configurable
|
* Configurable
|
||||||
*
|
*
|
||||||
* **************************************************/
|
* **************************************************/
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class ScriptHTTPRequests : IRegionModule, IHttpRequests
|
public class ScriptHTTPRequests : IRegionModule, IHttpRequests
|
||||||
{
|
{
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
|
private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
|
||||||
private object HttpListLock = new object();
|
private object HttpListLock = new object();
|
||||||
private string m_name = "HttpScriptRequests";
|
private string m_name = "HttpScriptRequests";
|
||||||
private int httpTimeout = 300;
|
private int httpTimeout = 30000;
|
||||||
|
|
||||||
// <request id, HttpRequestClass>
|
// <request id, HttpRequestClass>
|
||||||
private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests;
|
private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests;
|
||||||
|
|
||||||
public ScriptHTTPRequests()
|
public ScriptHTTPRequests()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
|
|
||||||
m_scene.RegisterModuleInterface<IHttpRequests>(this);
|
m_scene.RegisterModuleInterface<IHttpRequests>(this);
|
||||||
|
|
||||||
m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>();
|
m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return m_name; }
|
get { return m_name; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLUUID MakeHttpRequest(string url, string parameters, string body)
|
public LLUUID MakeHttpRequest(string url, string parameters, string body)
|
||||||
{
|
{
|
||||||
return LLUUID.Zero;
|
return LLUUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body)
|
public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body)
|
||||||
{
|
{
|
||||||
LLUUID reqID = LLUUID.Random();
|
LLUUID reqID = LLUUID.Random();
|
||||||
HttpRequestClass htc = new HttpRequestClass();
|
HttpRequestClass htc = new HttpRequestClass();
|
||||||
|
|
||||||
// Parameters are expected in {key, value, ... , key, value}
|
// Parameters are expected in {key, value, ... , key, value}
|
||||||
if (parameters != null)
|
if (parameters != null)
|
||||||
{
|
{
|
||||||
string[] parms = parameters.ToArray();
|
string[] parms = parameters.ToArray();
|
||||||
for (int i = 0; i < parms.Length/2; i += 2)
|
for (int i = 0; i < parms.Length/2; i += 2)
|
||||||
{
|
{
|
||||||
switch (Int32.Parse(parms[i]))
|
switch (Int32.Parse(parms[i]))
|
||||||
{
|
{
|
||||||
case HttpRequestClass.HTTP_METHOD:
|
case HttpRequestClass.HTTP_METHOD:
|
||||||
|
|
||||||
htc.httpMethod = parms[i + 1];
|
htc.httpMethod = parms[i + 1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HttpRequestClass.HTTP_MIMETYPE:
|
case HttpRequestClass.HTTP_MIMETYPE:
|
||||||
|
|
||||||
htc.httpMIMEType = parms[i + 1];
|
htc.httpMIMEType = parms[i + 1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HttpRequestClass.HTTP_BODY_MAXLENGTH:
|
case HttpRequestClass.HTTP_BODY_MAXLENGTH:
|
||||||
|
|
||||||
// TODO implement me
|
// TODO implement me
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HttpRequestClass.HTTP_VERIFY_CERT:
|
case HttpRequestClass.HTTP_VERIFY_CERT:
|
||||||
|
|
||||||
// TODO implement me
|
// TODO implement me
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
htc.localID = localID;
|
htc.localID = localID;
|
||||||
htc.itemID = itemID;
|
htc.itemID = itemID;
|
||||||
htc.url = url;
|
htc.url = url;
|
||||||
htc.reqID = reqID;
|
htc.reqID = reqID;
|
||||||
htc.httpTimeout = httpTimeout;
|
htc.httpTimeout = httpTimeout;
|
||||||
htc.outbound_body = body;
|
htc.outbound_body = body;
|
||||||
|
|
||||||
lock (HttpListLock)
|
lock (HttpListLock)
|
||||||
{
|
{
|
||||||
m_pendingRequests.Add(reqID, htc);
|
m_pendingRequests.Add(reqID, htc);
|
||||||
}
|
}
|
||||||
|
|
||||||
htc.process();
|
htc.process();
|
||||||
|
|
||||||
return reqID;
|
return reqID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopHttpRequest(uint m_localID, LLUUID m_itemID)
|
public void StopHttpRequest(uint m_localID, LLUUID m_itemID)
|
||||||
{
|
{
|
||||||
lock (HttpListLock)
|
if(m_pendingRequests != null) {
|
||||||
{
|
lock (HttpListLock)
|
||||||
HttpRequestClass tmpReq;
|
{
|
||||||
if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
|
HttpRequestClass tmpReq;
|
||||||
{
|
if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
|
||||||
tmpReq.Stop();
|
{
|
||||||
m_pendingRequests.Remove(m_itemID);
|
tmpReq.Stop();
|
||||||
}
|
m_pendingRequests.Remove(m_itemID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*
|
}
|
||||||
* TODO
|
|
||||||
* Not sure how important ordering is is here - the next first
|
/*
|
||||||
* one completed in the list is returned, based soley on its list
|
* TODO
|
||||||
* position, not the order in which the request was started or
|
* Not sure how important ordering is is here - the next first
|
||||||
* finsihed. I thought about setting up a queue for this, but
|
* one completed in the list is returned, based soley on its list
|
||||||
* it will need some refactoring and this works 'enough' right now
|
* position, not the order in which the request was started or
|
||||||
*/
|
* finsihed. I thought about setting up a queue for this, but
|
||||||
|
* it will need some refactoring and this works 'enough' right now
|
||||||
public HttpRequestClass GetNextCompletedRequest()
|
*/
|
||||||
{
|
|
||||||
lock (HttpListLock)
|
public HttpRequestClass GetNextCompletedRequest()
|
||||||
{
|
{
|
||||||
foreach (LLUUID luid in m_pendingRequests.Keys)
|
lock (HttpListLock)
|
||||||
{
|
{
|
||||||
HttpRequestClass tmpReq;
|
foreach (LLUUID luid in m_pendingRequests.Keys)
|
||||||
|
{
|
||||||
if (m_pendingRequests.TryGetValue(luid, out tmpReq))
|
HttpRequestClass tmpReq;
|
||||||
{
|
|
||||||
if (tmpReq.finished)
|
if (m_pendingRequests.TryGetValue(luid, out tmpReq))
|
||||||
{
|
{
|
||||||
m_pendingRequests.Remove(luid);
|
if (tmpReq.finished)
|
||||||
return tmpReq;
|
{
|
||||||
}
|
return tmpReq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
}
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
public void RemoveCompletedRequest(LLUUID id)
|
||||||
// HTTP REAQUEST
|
{
|
||||||
// This class was originally in LSLLongCmdHandler
|
lock (HttpListLock)
|
||||||
//
|
{
|
||||||
// TODO: setter/getter methods, maybe pass some in
|
HttpRequestClass tmpReq;
|
||||||
// constructor
|
if (m_pendingRequests.TryGetValue(id, out tmpReq))
|
||||||
//
|
{
|
||||||
|
tmpReq.Stop();
|
||||||
public class HttpRequestClass
|
tmpReq = null;
|
||||||
{
|
m_pendingRequests.Remove(id);
|
||||||
// Constants for parameters
|
}
|
||||||
public const int HTTP_METHOD = 0;
|
}
|
||||||
public const int HTTP_MIMETYPE = 1;
|
}
|
||||||
public const int HTTP_BODY_MAXLENGTH = 2;
|
|
||||||
public const int HTTP_VERIFY_CERT = 3;
|
}
|
||||||
|
|
||||||
// Parameter members and default values
|
//
|
||||||
public string httpMethod = "GET";
|
// HTTP REAQUEST
|
||||||
public string httpMIMEType = "text/plain;charset=utf-8";
|
// This class was originally in LSLLongCmdHandler
|
||||||
public int httpBodyMaxLen = 2048; // not implemented
|
//
|
||||||
public bool httpVerifyCert = true; // not implemented
|
// TODO: setter/getter methods, maybe pass some in
|
||||||
|
// constructor
|
||||||
// Request info
|
//
|
||||||
public uint localID;
|
|
||||||
public LLUUID itemID;
|
public class HttpRequestClass
|
||||||
public LLUUID reqID;
|
{
|
||||||
public int httpTimeout;
|
// Constants for parameters
|
||||||
public string url;
|
public const int HTTP_METHOD = 0;
|
||||||
public string outbound_body;
|
public const int HTTP_MIMETYPE = 1;
|
||||||
public DateTime next;
|
public const int HTTP_BODY_MAXLENGTH = 2;
|
||||||
public int status;
|
public const int HTTP_VERIFY_CERT = 3;
|
||||||
public bool finished;
|
|
||||||
public List<string> response_metadata;
|
// Parameter members and default values
|
||||||
public string response_body;
|
public string httpMethod = "GET";
|
||||||
public HttpWebRequest request;
|
public string httpMIMEType = "text/plain;charset=utf-8";
|
||||||
private Thread httpThread;
|
public int httpBodyMaxLen = 2048; // not implemented
|
||||||
|
public bool httpVerifyCert = true; // not implemented
|
||||||
public void process()
|
|
||||||
{
|
// Request info
|
||||||
httpThread = new Thread(SendRequest);
|
public uint localID;
|
||||||
httpThread.Name = "HttpRequestThread";
|
public LLUUID itemID;
|
||||||
httpThread.Priority = ThreadPriority.BelowNormal;
|
public LLUUID reqID;
|
||||||
httpThread.IsBackground = true;
|
public int httpTimeout;
|
||||||
httpThread.Start();
|
public string url;
|
||||||
}
|
public string outbound_body;
|
||||||
|
public DateTime next;
|
||||||
/*
|
public int status;
|
||||||
* TODO: More work on the response codes. Right now
|
public bool finished;
|
||||||
* returning 200 for success or 499 for exception
|
public List<string> response_metadata;
|
||||||
*/
|
public string response_body;
|
||||||
|
public HttpWebRequest request;
|
||||||
public void SendRequest()
|
private Thread httpThread;
|
||||||
{
|
|
||||||
HttpWebResponse response = null;
|
public void process()
|
||||||
StringBuilder sb = new StringBuilder();
|
{
|
||||||
byte[] buf = new byte[8192];
|
httpThread = new Thread(SendRequest);
|
||||||
string tempString = null;
|
httpThread.Name = "HttpRequestThread";
|
||||||
int count = 0;
|
httpThread.Priority = ThreadPriority.BelowNormal;
|
||||||
|
httpThread.IsBackground = true;
|
||||||
try
|
finished = false;
|
||||||
{
|
httpThread.Start();
|
||||||
request = (HttpWebRequest)
|
OpenSim.Framework.ThreadTracker.Add(httpThread);
|
||||||
WebRequest.Create(url);
|
}
|
||||||
request.Method = httpMethod;
|
|
||||||
request.ContentType = httpMIMEType;
|
/*
|
||||||
|
* TODO: More work on the response codes. Right now
|
||||||
request.Timeout = httpTimeout;
|
* returning 200 for success or 499 for exception
|
||||||
// execute the request
|
*/
|
||||||
response = (HttpWebResponse)
|
|
||||||
request.GetResponse();
|
public void SendRequest()
|
||||||
|
{
|
||||||
Stream resStream = response.GetResponseStream();
|
HttpWebResponse response = null;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
do
|
byte[] buf = new byte[8192];
|
||||||
{
|
string tempString = null;
|
||||||
// fill the buffer with data
|
int count = 0;
|
||||||
count = resStream.Read(buf, 0, buf.Length);
|
|
||||||
|
try
|
||||||
// make sure we read some data
|
{
|
||||||
if (count != 0)
|
request = (HttpWebRequest)
|
||||||
{
|
WebRequest.Create(url);
|
||||||
// translate from bytes to ASCII text
|
request.Method = httpMethod;
|
||||||
tempString = Encoding.ASCII.GetString(buf, 0, count);
|
request.ContentType = httpMIMEType;
|
||||||
|
|
||||||
// continue building the string
|
request.Timeout = httpTimeout;
|
||||||
sb.Append(tempString);
|
// execute the request
|
||||||
}
|
response = (HttpWebResponse)
|
||||||
} while (count > 0); // any more data to read?
|
request.GetResponse();
|
||||||
|
|
||||||
response_body = sb.ToString();
|
Stream resStream = response.GetResponseStream();
|
||||||
}
|
|
||||||
catch (Exception e)
|
do
|
||||||
{
|
{
|
||||||
status = 499;
|
// fill the buffer with data
|
||||||
response_body = e.Message;
|
count = resStream.Read(buf, 0, buf.Length);
|
||||||
finished = true;
|
|
||||||
return;
|
// make sure we read some data
|
||||||
}
|
if (count != 0)
|
||||||
|
{
|
||||||
status = 200;
|
// translate from bytes to ASCII text
|
||||||
finished = true;
|
tempString = Encoding.ASCII.GetString(buf, 0, count);
|
||||||
}
|
|
||||||
|
// continue building the string
|
||||||
public void Stop()
|
sb.Append(tempString);
|
||||||
{
|
}
|
||||||
try
|
} while (count > 0); // any more data to read?
|
||||||
{
|
|
||||||
httpThread.Abort();
|
response_body = sb.ToString();
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
}
|
status = 499;
|
||||||
}
|
response_body = e.Message;
|
||||||
}
|
finished = true;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = 200;
|
||||||
|
finished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
httpThread.Abort();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,194 +1,194 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class SunModule : IRegionModule
|
public class SunModule : IRegionModule
|
||||||
{
|
{
|
||||||
private const double m_real_day = 24.0;
|
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private const int m_default_frame = 100;
|
|
||||||
private int m_frame_mod;
|
private const double m_real_day = 24.0;
|
||||||
private double m_day_length;
|
private const int m_default_frame = 100;
|
||||||
private int m_dilation;
|
private int m_frame_mod;
|
||||||
private int m_frame;
|
private double m_day_length;
|
||||||
private long m_start;
|
private int m_dilation;
|
||||||
|
private int m_frame;
|
||||||
private Scene m_scene;
|
private long m_start;
|
||||||
private LogBase m_log;
|
|
||||||
|
private Scene m_scene;
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
|
||||||
{
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
m_start = DateTime.Now.Ticks;
|
{
|
||||||
m_frame = 0;
|
m_start = DateTime.Now.Ticks;
|
||||||
|
m_frame = 0;
|
||||||
// Just in case they don't have the stanzas
|
|
||||||
try
|
// Just in case they don't have the stanzas
|
||||||
{
|
try
|
||||||
m_day_length = config.Configs["Sun"].GetDouble("day_length", m_real_day);
|
{
|
||||||
m_frame_mod = config.Configs["Sun"].GetInt("frame_rate", m_default_frame);
|
m_day_length = config.Configs["Sun"].GetDouble("day_length", m_real_day);
|
||||||
}
|
m_frame_mod = config.Configs["Sun"].GetInt("frame_rate", m_default_frame);
|
||||||
catch (Exception)
|
}
|
||||||
{
|
catch (Exception)
|
||||||
m_day_length = m_real_day;
|
{
|
||||||
m_frame_mod = m_default_frame;
|
m_day_length = m_real_day;
|
||||||
}
|
m_frame_mod = m_default_frame;
|
||||||
|
}
|
||||||
m_dilation = (int) (m_real_day/m_day_length);
|
|
||||||
m_scene = scene;
|
m_dilation = (int) (m_real_day/m_day_length);
|
||||||
m_log = MainLog.Instance;
|
m_scene = scene;
|
||||||
scene.EventManager.OnFrame += SunUpdate;
|
scene.EventManager.OnFrame += SunUpdate;
|
||||||
scene.EventManager.OnNewClient += SunToClient;
|
scene.EventManager.OnNewClient += SunToClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "SunModule"; }
|
get { return "SunModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SunToClient(IClientAPI client)
|
public void SunToClient(IClientAPI client)
|
||||||
{
|
{
|
||||||
client.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f));
|
client.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SunUpdate()
|
public void SunUpdate()
|
||||||
{
|
{
|
||||||
if (m_frame < m_frame_mod)
|
if (m_frame < m_frame_mod)
|
||||||
{
|
{
|
||||||
m_frame++;
|
m_frame++;
|
||||||
return;
|
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();
|
List<ScenePresence> avatars = m_scene.GetAvatars();
|
||||||
foreach (ScenePresence avatar in avatars)
|
foreach (ScenePresence avatar in avatars)
|
||||||
{
|
{
|
||||||
avatar.ControllingClient.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f));
|
avatar.ControllingClient.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f));
|
||||||
}
|
}
|
||||||
m_frame = 0;
|
m_frame = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hour of the Day figures out the hour of the day as a float.
|
// Hour of the Day figures out the hour of the day as a float.
|
||||||
// The intent here is that we seed hour of the day with real
|
// The intent here is that we seed hour of the day with real
|
||||||
// time when the simulator starts, then run time forward
|
// time when the simulator starts, then run time forward
|
||||||
// faster based on time dilation factor. This means that
|
// faster based on time dilation factor. This means that
|
||||||
// ticks don't get out of hand
|
// ticks don't get out of hand
|
||||||
private double HourOfTheDay()
|
private double HourOfTheDay()
|
||||||
{
|
{
|
||||||
long m_addticks = (DateTime.Now.Ticks - m_start)*m_dilation;
|
long m_addticks = (DateTime.Now.Ticks - m_start)*m_dilation;
|
||||||
DateTime dt = new DateTime(m_start + m_addticks);
|
DateTime dt = new DateTime(m_start + m_addticks);
|
||||||
return (double) dt.Hour + ((double) dt.Minute/60.0);
|
return (double) dt.Hour + ((double) dt.Minute/60.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LLVector3 SunPos(double hour)
|
private LLVector3 SunPos(double hour)
|
||||||
{
|
{
|
||||||
// now we have our radian position
|
// now we have our radian position
|
||||||
double rad = (hour/m_real_day)*2*Math.PI - (Math.PI/2.0);
|
double rad = (hour/m_real_day)*2*Math.PI - (Math.PI/2.0);
|
||||||
double z = Math.Sin(rad);
|
double z = Math.Sin(rad);
|
||||||
double x = Math.Cos(rad);
|
double x = Math.Cos(rad);
|
||||||
return new LLVector3((float) x, 0f, (float) z);
|
return new LLVector3((float) x, 0f, (float) z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: clear this out. This is here so that I remember to
|
// TODO: clear this out. This is here so that I remember to
|
||||||
// figure out if we need those other packet fields that I've
|
// figure out if we need those other packet fields that I've
|
||||||
// left out so far
|
// left out so far
|
||||||
//
|
//
|
||||||
// public void SendViewerTime(int phase)
|
// public void SendViewerTime(int phase)
|
||||||
// {
|
// {
|
||||||
// Console.WriteLine("SunPhase: {0}", phase);
|
// Console.WriteLine("SunPhase: {0}", phase);
|
||||||
// SimulatorViewerTimeMessagePacket viewertime = new SimulatorViewerTimeMessagePacket();
|
// SimulatorViewerTimeMessagePacket viewertime = new SimulatorViewerTimeMessagePacket();
|
||||||
// //viewertime.TimeInfo.SecPerDay = 86400;
|
// //viewertime.TimeInfo.SecPerDay = 86400;
|
||||||
// // viewertime.TimeInfo.SecPerYear = 31536000;
|
// // viewertime.TimeInfo.SecPerYear = 31536000;
|
||||||
// viewertime.TimeInfo.SecPerDay = 1000;
|
// viewertime.TimeInfo.SecPerDay = 1000;
|
||||||
// viewertime.TimeInfo.SecPerYear = 365000;
|
// viewertime.TimeInfo.SecPerYear = 365000;
|
||||||
// viewertime.TimeInfo.SunPhase = 1;
|
// viewertime.TimeInfo.SunPhase = 1;
|
||||||
// int sunPhase = (phase + 2)/2;
|
// int sunPhase = (phase + 2)/2;
|
||||||
// if ((sunPhase < 6) || (sunPhase > 36))
|
// if ((sunPhase < 6) || (sunPhase > 36))
|
||||||
// {
|
// {
|
||||||
// viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f);
|
// viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f);
|
||||||
// Console.WriteLine("sending night");
|
// Console.WriteLine("sending night");
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
// if (sunPhase < 12)
|
// if (sunPhase < 12)
|
||||||
// {
|
// {
|
||||||
// sunPhase = 12;
|
// sunPhase = 12;
|
||||||
// }
|
// }
|
||||||
// sunPhase = sunPhase - 12;
|
// sunPhase = sunPhase - 12;
|
||||||
//
|
//
|
||||||
// float yValue = 0.1f*(sunPhase);
|
// float yValue = 0.1f*(sunPhase);
|
||||||
// Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue);
|
// Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue);
|
||||||
// if (yValue > 1.2f)
|
// if (yValue > 1.2f)
|
||||||
// {
|
// {
|
||||||
// yValue = yValue - 1.2f;
|
// yValue = yValue - 1.2f;
|
||||||
// }
|
// }
|
||||||
// if (yValue > 1)
|
// if (yValue > 1)
|
||||||
// {
|
// {
|
||||||
// yValue = 1;
|
// yValue = 1;
|
||||||
// }
|
// }
|
||||||
// if (yValue < 0)
|
// if (yValue < 0)
|
||||||
// {
|
// {
|
||||||
// yValue = 0;
|
// yValue = 0;
|
||||||
// }
|
// }
|
||||||
// if (sunPhase < 14)
|
// if (sunPhase < 14)
|
||||||
// {
|
// {
|
||||||
// yValue = 1 - yValue;
|
// yValue = 1 - yValue;
|
||||||
// }
|
// }
|
||||||
// if (sunPhase < 12)
|
// if (sunPhase < 12)
|
||||||
// {
|
// {
|
||||||
// yValue *= -1;
|
// yValue *= -1;
|
||||||
// }
|
// }
|
||||||
// viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f);
|
// viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f);
|
||||||
// Console.WriteLine("sending sun update " + yValue);
|
// Console.WriteLine("sending sun update " + yValue);
|
||||||
// }
|
// }
|
||||||
// viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f);
|
// viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f);
|
||||||
// viewertime.TimeInfo.UsecSinceStart = (ulong) Util.UnixTimeSinceEpoch();
|
// viewertime.TimeInfo.UsecSinceStart = (ulong) Util.UnixTimeSinceEpoch();
|
||||||
// // OutPacket(viewertime);
|
// // OutPacket(viewertime);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
internal class TeleportModule
|
internal class TeleportModule
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,174 +1,216 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using libsecondlife.Packets;
|
using libsecondlife.Packets;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
//this is a first attempt, to start breaking the mess thats called the assetcache up.
|
//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
|
// basically this should be the texture sending (to clients) code moved out of assetcache
|
||||||
//and some small clean up
|
//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
|
||||||
public class TextureDownloadModule : IRegionModule
|
{
|
||||||
{
|
//private static readonly log4net.ILog m_log
|
||||||
private Scene m_scene;
|
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private List<Scene> m_scenes = new List<Scene>();
|
|
||||||
|
private Scene m_scene;
|
||||||
private readonly BlockingQueue<TextureSender> m_queueSenders = new BlockingQueue<TextureSender>();
|
private List<Scene> m_scenes = new List<Scene>();
|
||||||
|
|
||||||
private readonly Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices =
|
/// <summary>
|
||||||
new Dictionary<LLUUID, UserTextureDownloadService>();
|
/// There is one queue for all textures waiting to be sent, regardless of the requesting user.
|
||||||
|
/// </summary>
|
||||||
private Thread m_thread;
|
private readonly BlockingQueue<TextureSender> m_queueSenders = new BlockingQueue<TextureSender>();
|
||||||
|
|
||||||
public TextureDownloadModule()
|
/// <summary>
|
||||||
{
|
/// Each user has their own texture download service.
|
||||||
}
|
/// </summary>
|
||||||
|
private readonly Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices =
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
new Dictionary<LLUUID, UserTextureDownloadService>();
|
||||||
{
|
|
||||||
if (m_scene == null)
|
private Thread m_thread;
|
||||||
{
|
|
||||||
//Console.WriteLine("Creating Texture download module");
|
public TextureDownloadModule()
|
||||||
m_thread = new Thread(new ThreadStart(ProcessTextureSenders));
|
{
|
||||||
m_thread.IsBackground = true;
|
}
|
||||||
m_thread.Start();
|
|
||||||
}
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
|
{
|
||||||
if (!m_scenes.Contains(scene))
|
if (m_scene == null)
|
||||||
{
|
{
|
||||||
m_scenes.Add(scene);
|
//Console.WriteLine("Creating Texture download module");
|
||||||
m_scene = scene;
|
m_thread = new Thread(new ThreadStart(ProcessTextureSenders));
|
||||||
m_scene.EventManager.OnNewClient += NewClient;
|
m_thread.Name = "ProcessTextureSenderThread";
|
||||||
m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence;
|
m_thread.IsBackground = true;
|
||||||
}
|
m_thread.Start();
|
||||||
}
|
OpenSim.Framework.ThreadTracker.Add(m_thread);
|
||||||
|
}
|
||||||
private void EventManager_OnRemovePresence(LLUUID agentId)
|
|
||||||
{
|
if (!m_scenes.Contains(scene))
|
||||||
UserTextureDownloadService textureService;
|
{
|
||||||
|
m_scenes.Add(scene);
|
||||||
lock (m_userTextureServices)
|
m_scene = scene;
|
||||||
{
|
m_scene.EventManager.OnNewClient += NewClient;
|
||||||
if( m_userTextureServices.TryGetValue( agentId, out textureService ))
|
m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence;
|
||||||
{
|
}
|
||||||
textureService.Close();
|
}
|
||||||
|
|
||||||
m_userTextureServices.Remove(agentId);
|
/// <summary>
|
||||||
}
|
/// Cleanup the texture service related objects for the removed presence.
|
||||||
}
|
/// </summary>
|
||||||
}
|
/// <param name="agentId"> </param>
|
||||||
|
private void EventManager_OnRemovePresence(LLUUID agentId)
|
||||||
public void PostInitialise()
|
{
|
||||||
{
|
UserTextureDownloadService textureService;
|
||||||
}
|
|
||||||
|
lock (m_userTextureServices)
|
||||||
public void Close()
|
{
|
||||||
{
|
if (m_userTextureServices.TryGetValue(agentId, out textureService))
|
||||||
}
|
{
|
||||||
|
textureService.Close();
|
||||||
public string Name
|
|
||||||
{
|
m_userTextureServices.Remove(agentId);
|
||||||
get { return "TextureDownloadModule"; }
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public bool IsSharedModule
|
|
||||||
{
|
public void PostInitialise()
|
||||||
get { return false; }
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NewClient(IClientAPI client)
|
public void Close()
|
||||||
{
|
{
|
||||||
client.OnRequestTexture += TextureRequest;
|
}
|
||||||
}
|
|
||||||
|
public string Name
|
||||||
private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService)
|
{
|
||||||
{
|
get { return "TextureDownloadModule"; }
|
||||||
lock (m_userTextureServices)
|
}
|
||||||
{
|
|
||||||
if (m_userTextureServices.TryGetValue(userID, out textureService))
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
return true;
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
textureService = new UserTextureDownloadService(m_scene, m_queueSenders);
|
public void NewClient(IClientAPI client)
|
||||||
m_userTextureServices.Add(userID, textureService);
|
{
|
||||||
return true;
|
client.OnRequestTexture += TextureRequest;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
public void TextureRequest(Object sender, TextureRequestArgs e)
|
/// Does this user have a registered texture download service?
|
||||||
{
|
/// </summary>
|
||||||
IClientAPI client = (IClientAPI) sender;
|
/// <param name="userID"></param>
|
||||||
UserTextureDownloadService textureService;
|
/// <param name="textureService"></param>
|
||||||
if (TryGetUserTextureService(client.AgentId, out textureService))
|
/// <returns>Always returns true, since a service is created if one does not already exist</returns>
|
||||||
{
|
private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService)
|
||||||
textureService.HandleTextureRequest(client, e);
|
{
|
||||||
}
|
lock (m_userTextureServices)
|
||||||
}
|
{
|
||||||
|
if (m_userTextureServices.TryGetValue(userID, out textureService))
|
||||||
public void ProcessTextureSenders()
|
{
|
||||||
{
|
return true;
|
||||||
while (true)
|
}
|
||||||
{
|
|
||||||
TextureSender sender = m_queueSenders.Dequeue();
|
textureService = new UserTextureDownloadService(m_scene, m_queueSenders);
|
||||||
if (sender.Cancel)
|
m_userTextureServices.Add(userID, textureService);
|
||||||
{
|
return true;
|
||||||
TextureSent(sender);
|
}
|
||||||
|
}
|
||||||
sender.Cancel = false;
|
|
||||||
}
|
/// <summary>
|
||||||
else
|
/// Start the process of requesting a given texture.
|
||||||
{
|
/// </summary>
|
||||||
bool finished = sender.SendTexturePacket();
|
/// <param name="sender"> </param>
|
||||||
if (finished)
|
/// <param name="e"></param>
|
||||||
{
|
public void TextureRequest(Object sender, TextureRequestArgs e)
|
||||||
TextureSent(sender);
|
{
|
||||||
}
|
IClientAPI client = (IClientAPI) sender;
|
||||||
else
|
UserTextureDownloadService textureService;
|
||||||
{
|
if (TryGetUserTextureService(client.AgentId, out textureService))
|
||||||
m_queueSenders.Enqueue(sender);
|
{
|
||||||
}
|
textureService.HandleTextureRequest(client, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
private void TextureSent(TextureSender sender)
|
/// Entry point for the thread dedicated to processing the texture queue.
|
||||||
{
|
/// </summary>
|
||||||
sender.Sending = false;
|
public void ProcessTextureSenders()
|
||||||
}
|
{
|
||||||
}
|
TextureSender sender = null;
|
||||||
}
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
sender = m_queueSenders.Dequeue();
|
||||||
|
|
||||||
|
if (sender.Cancel)
|
||||||
|
{
|
||||||
|
TextureSent(sender);
|
||||||
|
|
||||||
|
sender.Cancel = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool finished = sender.SendTexturePacket();
|
||||||
|
if (finished)
|
||||||
|
{
|
||||||
|
TextureSent(sender);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_queueSenders.Enqueue(sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that any sender we currently have can get garbage collected
|
||||||
|
sender = null;
|
||||||
|
|
||||||
|
//m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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,136 +1,204 @@
|
||||||
using System;
|
/*
|
||||||
using libsecondlife;
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
using libsecondlife.Packets;
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
using OpenSim.Framework;
|
*
|
||||||
using OpenSim.Framework.Console;
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
namespace OpenSim.Region.Environment.Modules
|
* * Redistributions of source code must retain the above copyright
|
||||||
{
|
* notice, this list of conditions and the following disclaimer.
|
||||||
public class TextureSender
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
{
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
public int counter = 0;
|
* documentation and/or other materials provided with the distribution.
|
||||||
private AssetBase m_asset;
|
* * Neither the name of the OpenSim Project nor the
|
||||||
public long DataPointer = 0;
|
* names of its contributors may be used to endorse or promote products
|
||||||
public int NumPackets = 0;
|
* derived from this software without specific prior written permission.
|
||||||
public int PacketCounter = 0;
|
*
|
||||||
public bool Cancel = false;
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
public bool ImageLoaded = false;
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
public bool Sending = false;
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
public IClientAPI RequestUser;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
public LLUUID RequestedAssetID;
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
public int RequestedDiscardLevel = -1;
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
public uint StartPacketNumber = 0;
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
// private int m_sentDiscardLevel = -1;
|
*
|
||||||
|
*/
|
||||||
public TextureSender(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber)
|
|
||||||
{
|
using System;
|
||||||
RequestUser = client;
|
using libsecondlife;
|
||||||
RequestedAssetID = textureID;
|
using libsecondlife.Packets;
|
||||||
RequestedDiscardLevel = discardLevel;
|
using OpenSim.Framework;
|
||||||
StartPacketNumber = packetNumber;
|
using OpenSim.Framework.Console;
|
||||||
}
|
|
||||||
|
namespace OpenSim.Region.Environment.Modules
|
||||||
public void TextureReceived(AssetBase asset)
|
{
|
||||||
{
|
/// <summary>
|
||||||
m_asset = asset;
|
/// A TextureSender handles the process of receiving a texture requested by the client from the
|
||||||
NumPackets = CalculateNumPackets(asset.Data.Length);
|
/// AssetCache, and then sending that texture back to the client.
|
||||||
PacketCounter = (int) StartPacketNumber;
|
/// </summary>
|
||||||
ImageLoaded = true;
|
public class TextureSender
|
||||||
}
|
{
|
||||||
|
private static readonly log4net.ILog m_log
|
||||||
public void UpdateRequest(int discardLevel, uint packetNumber)
|
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
{
|
|
||||||
RequestedDiscardLevel = discardLevel;
|
/// <summary>
|
||||||
StartPacketNumber = packetNumber;
|
/// Records the number of times texture send has been called.
|
||||||
PacketCounter = (int) StartPacketNumber;
|
/// </summary>
|
||||||
}
|
public int counter = 0;
|
||||||
|
|
||||||
public bool SendTexturePacket()
|
/// <summary>
|
||||||
{
|
/// Holds the texture asset to send.
|
||||||
SendPacket();
|
/// </summary>
|
||||||
counter++;
|
private AssetBase m_asset;
|
||||||
if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
|
|
||||||
((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1)))))
|
//public LLUUID assetID { get { return m_asset.FullID; } }
|
||||||
{
|
|
||||||
return true;
|
/// <summary>
|
||||||
}
|
/// This is actually the number of extra packets required to send the texture data! We always assume
|
||||||
return false;
|
/// at least one is required.
|
||||||
}
|
/// </summary>
|
||||||
|
private int NumPackets = 0;
|
||||||
private void SendPacket()
|
|
||||||
{
|
/// <summary>
|
||||||
if (PacketCounter <= NumPackets)
|
/// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts
|
||||||
{
|
/// at the 600th byte (0th indexed).
|
||||||
if (PacketCounter == 0)
|
/// </summary>
|
||||||
{
|
private int PacketCounter = 0;
|
||||||
if (NumPackets == 0)
|
|
||||||
{
|
public bool Cancel = false;
|
||||||
ImageDataPacket im = new ImageDataPacket();
|
public bool ImageLoaded = false;
|
||||||
im.Header.Reliable = false;
|
public bool Sending = false;
|
||||||
im.ImageID.Packets = 1;
|
|
||||||
im.ImageID.ID = m_asset.FullID;
|
private IClientAPI RequestUser;
|
||||||
im.ImageID.Size = (uint) m_asset.Data.Length;
|
|
||||||
im.ImageData.Data = m_asset.Data;
|
private int RequestedDiscardLevel = -1;
|
||||||
im.ImageID.Codec = 2;
|
private uint StartPacketNumber = 0;
|
||||||
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
|
|
||||||
PacketCounter++;
|
public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
|
||||||
}
|
{
|
||||||
else
|
RequestUser = client;
|
||||||
{
|
RequestedDiscardLevel = discardLevel;
|
||||||
ImageDataPacket im = new ImageDataPacket();
|
StartPacketNumber = packetNumber;
|
||||||
im.Header.Reliable = false;
|
}
|
||||||
im.ImageID.Packets = (ushort) (NumPackets);
|
|
||||||
im.ImageID.ID = m_asset.FullID;
|
/// <summary>
|
||||||
im.ImageID.Size = (uint) m_asset.Data.Length;
|
/// Load up the texture data to send.
|
||||||
im.ImageData.Data = new byte[600];
|
/// </summary>
|
||||||
Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600);
|
/// <param name="asset">
|
||||||
im.ImageID.Codec = 2;
|
/// A <see cref="AssetBase"/>
|
||||||
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
|
/// </param>
|
||||||
PacketCounter++;
|
public void TextureReceived(AssetBase asset)
|
||||||
}
|
{
|
||||||
}
|
m_asset = asset;
|
||||||
else
|
NumPackets = CalculateNumPackets(asset.Data.Length);
|
||||||
{
|
PacketCounter = (int) StartPacketNumber;
|
||||||
ImagePacketPacket im = new ImagePacketPacket();
|
ImageLoaded = true;
|
||||||
im.Header.Reliable = false;
|
}
|
||||||
im.ImageID.Packet = (ushort) (PacketCounter);
|
|
||||||
im.ImageID.ID = m_asset.FullID;
|
public void UpdateRequest(int discardLevel, uint packetNumber)
|
||||||
int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1));
|
{
|
||||||
if (size > 1000) size = 1000;
|
RequestedDiscardLevel = discardLevel;
|
||||||
im.ImageData.Data = new byte[size];
|
StartPacketNumber = packetNumber;
|
||||||
try
|
PacketCounter = (int) StartPacketNumber;
|
||||||
{
|
}
|
||||||
Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size);
|
|
||||||
}
|
/// <summary>
|
||||||
catch (ArgumentOutOfRangeException)
|
/// Send a texture packet to the client.
|
||||||
{
|
/// </summary>
|
||||||
MainLog.Instance.Error("TEXTURE",
|
/// <returns>True if the last packet has been sent, false otherwise.</returns>
|
||||||
"Unable to separate texture into multiple packets: Array bounds failure on asset:" +
|
public bool SendTexturePacket()
|
||||||
m_asset.FullID.ToString() );
|
{
|
||||||
return;
|
SendPacket();
|
||||||
}
|
counter++;
|
||||||
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
|
if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
|
||||||
PacketCounter++;
|
((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1)))))
|
||||||
}
|
{
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
private int CalculateNumPackets(int length)
|
}
|
||||||
{
|
|
||||||
int numPackets = 0;
|
/// <summary>
|
||||||
|
/// Sends a texture packet to the client.
|
||||||
if (length > 600)
|
/// </summary>
|
||||||
{
|
private void SendPacket()
|
||||||
//over 600 bytes so split up file
|
{
|
||||||
int restData = (length - 600);
|
if (PacketCounter <= NumPackets)
|
||||||
int restPackets = ((restData + 999)/1000);
|
{
|
||||||
numPackets = restPackets;
|
if (PacketCounter == 0)
|
||||||
}
|
{
|
||||||
|
if (NumPackets == 0)
|
||||||
return numPackets;
|
{
|
||||||
}
|
ImageDataPacket im = new ImageDataPacket();
|
||||||
}
|
im.Header.Reliable = false;
|
||||||
}
|
im.ImageID.Packets = 1;
|
||||||
|
im.ImageID.ID = m_asset.FullID;
|
||||||
|
im.ImageID.Size = (uint) m_asset.Data.Length;
|
||||||
|
im.ImageData.Data = m_asset.Data;
|
||||||
|
im.ImageID.Codec = 2;
|
||||||
|
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
|
||||||
|
PacketCounter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImageDataPacket im = new ImageDataPacket();
|
||||||
|
im.Header.Reliable = false;
|
||||||
|
im.ImageID.Packets = (ushort) (NumPackets);
|
||||||
|
im.ImageID.ID = m_asset.FullID;
|
||||||
|
im.ImageID.Size = (uint) m_asset.Data.Length;
|
||||||
|
im.ImageData.Data = new byte[600];
|
||||||
|
Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600);
|
||||||
|
im.ImageID.Codec = 2;
|
||||||
|
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
|
||||||
|
PacketCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImagePacketPacket im = new ImagePacketPacket();
|
||||||
|
im.Header.Reliable = false;
|
||||||
|
im.ImageID.Packet = (ushort) (PacketCounter);
|
||||||
|
im.ImageID.ID = m_asset.FullID;
|
||||||
|
int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1));
|
||||||
|
if (size > 1000) size = 1000;
|
||||||
|
im.ImageData.Data = new byte[size];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size);
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
m_log.Error("[TEXTURE]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
|
||||||
|
m_asset.FullID.ToString() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
|
||||||
|
PacketCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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;
|
||||||
|
|
||||||
|
if (length > 600)
|
||||||
|
{
|
||||||
|
//over 600 bytes so split up file
|
||||||
|
int restData = (length - 600);
|
||||||
|
int restPackets = ((restData + 999)/1000);
|
||||||
|
numPackets = restPackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numPackets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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,109 +1,191 @@
|
||||||
using System;
|
/*
|
||||||
using System.Collections.Generic;
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
using libsecondlife;
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
using OpenSim.Framework;
|
*
|
||||||
using OpenSim.Framework.Console;
|
* Redistribution and use in source and binary forms, with or without
|
||||||
using OpenSim.Region.Environment.Scenes;
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
namespace OpenSim.Region.Environment.Modules
|
* notice, this list of conditions and the following disclaimer.
|
||||||
{
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
public class UserTextureDownloadService
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
{
|
* documentation and/or other materials provided with the distribution.
|
||||||
private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
|
* * Neither the name of the OpenSim Project nor the
|
||||||
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
|
* names of its contributors may be used to endorse or promote products
|
||||||
private readonly Scene m_scene;
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue)
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
{
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
m_scene = scene;
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
m_sharedSendersQueue = sharedQueue;
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
}
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
{
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
TextureSender textureSender;
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//TODO: should be working out the data size/ number of packets to be sent for each discard level
|
*
|
||||||
if ((e.DiscardLevel >= 0) || (e.Priority != 0))
|
*/
|
||||||
{
|
|
||||||
lock (m_textureSenders)
|
using System;
|
||||||
{
|
using System.Collections.Generic;
|
||||||
if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
|
using libsecondlife;
|
||||||
{
|
using OpenSim.Framework;
|
||||||
textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Region.Environment.Scenes;
|
||||||
if ((textureSender.ImageLoaded) &&
|
|
||||||
(textureSender.Sending == false))
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
EnqueueTextureSender(textureSender);
|
/// <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
|
||||||
else
|
/// asset cache).
|
||||||
{
|
/// </summary>
|
||||||
TextureSender requestHandler =
|
public class UserTextureDownloadService
|
||||||
new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber);
|
{
|
||||||
m_textureSenders.Add(e.RequestedAssetID, requestHandler);
|
private static readonly log4net.ILog m_log
|
||||||
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback);
|
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
}
|
|
||||||
}
|
/// <summary>
|
||||||
}
|
/// Holds texture senders before they have received the appropriate texture from the asset cache.
|
||||||
else
|
/// </summary>
|
||||||
{
|
private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
|
||||||
lock (m_textureSenders)
|
|
||||||
{
|
/// <summary>
|
||||||
if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
|
/// Texture Senders are placed in this queue once they have received their texture from the asset
|
||||||
{
|
/// cache. Another module actually invokes the send.
|
||||||
textureSender.Cancel = true;
|
/// </summary>
|
||||||
}
|
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
|
||||||
}
|
|
||||||
}
|
private readonly Scene m_scene;
|
||||||
}
|
|
||||||
|
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue)
|
||||||
public void TextureCallback(LLUUID textureID, AssetBase asset)
|
{
|
||||||
{
|
m_scene = scene;
|
||||||
lock (m_textureSenders)
|
m_sharedSendersQueue = sharedQueue;
|
||||||
{
|
}
|
||||||
TextureSender textureSender;
|
|
||||||
|
/// <summary>
|
||||||
if (m_textureSenders.TryGetValue(textureID, out textureSender))
|
/// Handle a texture request. This involves creating a texture sender and placing it on the
|
||||||
{
|
/// previously passed in shared queue.
|
||||||
if (!textureSender.ImageLoaded)
|
/// </summary>
|
||||||
{
|
/// <param name="client"> </param>
|
||||||
textureSender.TextureReceived(asset);
|
/// <param name="e"></param>
|
||||||
|
public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
|
||||||
EnqueueTextureSender(textureSender);
|
{
|
||||||
}
|
TextureSender textureSender;
|
||||||
}
|
|
||||||
else
|
//TODO: should be working out the data size/ number of packets to be sent for each discard level
|
||||||
{
|
if ((e.DiscardLevel >= 0) || (e.Priority != 0))
|
||||||
throw new Exception("Got a texture with no sender object to handle it, this shouldn't happen");
|
{
|
||||||
}
|
lock (m_textureSenders)
|
||||||
}
|
{
|
||||||
}
|
if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
|
||||||
|
{
|
||||||
private void EnqueueTextureSender(TextureSender textureSender)
|
// If we've received new non UUID information for this request and it hasn't dispatched
|
||||||
{
|
// yet, then update the request accordingly.
|
||||||
textureSender.Cancel = false;
|
textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
|
||||||
textureSender.Sending = true;
|
}
|
||||||
textureSender.counter = 0;
|
else
|
||||||
|
{
|
||||||
if (!m_sharedSendersQueue.Contains(textureSender))
|
//m_log.DebugFormat("[USER TEXTURE DOWNLOAD]: Adding download stat {0}", e.RequestedAssetID);
|
||||||
{
|
m_scene.AddPendingDownloads(1);
|
||||||
m_sharedSendersQueue.Enqueue(textureSender);
|
|
||||||
}
|
TextureSender requestHandler =
|
||||||
}
|
new TextureSender(client, e.DiscardLevel, e.PacketNumber);
|
||||||
|
m_textureSenders.Add(e.RequestedAssetID, requestHandler);
|
||||||
internal void Close()
|
|
||||||
{
|
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true);
|
||||||
lock (m_textureSenders)
|
}
|
||||||
{
|
}
|
||||||
foreach( TextureSender textureSender in m_textureSenders.Values )
|
}
|
||||||
{
|
else
|
||||||
textureSender.Cancel = true;
|
{
|
||||||
}
|
lock (m_textureSenders)
|
||||||
|
{
|
||||||
m_textureSenders.Clear();
|
if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
|
||||||
}
|
{
|
||||||
}
|
textureSender.Cancel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The callback for the asset cache when a texture has been retrieved. This method queues the
|
||||||
|
/// texture sender for processing.
|
||||||
|
/// </summary>
|
||||||
|
/// <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(texture);
|
||||||
|
EnqueueTextureSender(textureSender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
textureSender.Sending = true;
|
||||||
|
textureSender.counter = 0;
|
||||||
|
|
||||||
|
if (!m_sharedSendersQueue.Contains(textureSender))
|
||||||
|
{
|
||||||
|
m_sharedSendersQueue.Enqueue(textureSender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Close this module.
|
||||||
|
/// </summary>
|
||||||
|
internal void Close()
|
||||||
|
{
|
||||||
|
lock (m_textureSenders)
|
||||||
|
{
|
||||||
|
foreach( TextureSender textureSender in m_textureSenders.Values )
|
||||||
|
{
|
||||||
|
textureSender.Cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_textureSenders.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,202 +1,226 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Scenes;
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
public class XferModule : IRegionModule, IXfer
|
public class XferModule : IRegionModule, IXfer
|
||||||
{
|
{
|
||||||
public Dictionary<string, byte[]> NewFiles = new Dictionary<string, byte[]>();
|
public Dictionary<string, byte[]> NewFiles = new Dictionary<string, byte[]>();
|
||||||
public Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>();
|
public Dictionary<ulong, XferDownLoad> Transfers = new Dictionary<ulong, XferDownLoad>();
|
||||||
|
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
|
||||||
public XferModule()
|
public XferModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_scene.EventManager.OnNewClient += NewClient;
|
m_scene.EventManager.OnNewClient += NewClient;
|
||||||
|
|
||||||
m_scene.RegisterModuleInterface<IXfer>(this);
|
m_scene.RegisterModuleInterface<IXfer>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "XferModule"; }
|
get { return "XferModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
{
|
{
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NewClient(IClientAPI client)
|
public void NewClient(IClientAPI client)
|
||||||
{
|
{
|
||||||
client.OnRequestXfer += RequestXfer;
|
client.OnRequestXfer += RequestXfer;
|
||||||
client.OnConfirmXfer += AckPacket;
|
client.OnConfirmXfer += AckPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="remoteClient"></param>
|
/// <param name="remoteClient"></param>
|
||||||
/// <param name="xferID"></param>
|
/// <param name="xferID"></param>
|
||||||
/// <param name="fileName"></param>
|
/// <param name="fileName"></param>
|
||||||
public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName)
|
public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName)
|
||||||
{
|
{
|
||||||
lock (NewFiles)
|
lock (NewFiles)
|
||||||
{
|
{
|
||||||
if (NewFiles.ContainsKey(fileName))
|
if (NewFiles.ContainsKey(fileName))
|
||||||
{
|
{
|
||||||
if (!Transfers.ContainsKey(xferID))
|
if (!Transfers.ContainsKey(xferID))
|
||||||
{
|
{
|
||||||
byte[] fileData = NewFiles[fileName];
|
byte[] fileData = NewFiles[fileName];
|
||||||
XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
|
XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
|
||||||
Transfers.Add(xferID, transaction);
|
Transfers.Add(xferID, transaction);
|
||||||
NewFiles.Remove(fileName);
|
NewFiles.Remove(fileName);
|
||||||
transaction.StartSend();
|
|
||||||
}
|
if (transaction.StartSend())
|
||||||
}
|
{
|
||||||
}
|
Transfers.Remove(xferID);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet)
|
}
|
||||||
{
|
}
|
||||||
if (Transfers.ContainsKey(xferID))
|
}
|
||||||
{
|
|
||||||
Transfers[xferID].AckPacket(packet);
|
public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet)
|
||||||
}
|
{
|
||||||
}
|
if (Transfers.ContainsKey(xferID))
|
||||||
|
{
|
||||||
public bool AddNewFile(string fileName, byte[] data)
|
if (Transfers[xferID].AckPacket(packet))
|
||||||
{
|
{
|
||||||
lock (NewFiles)
|
{
|
||||||
{
|
Transfers.Remove(xferID);
|
||||||
if (NewFiles.ContainsKey(fileName))
|
}
|
||||||
{
|
}
|
||||||
NewFiles[fileName] = data;
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
public bool AddNewFile(string fileName, byte[] data)
|
||||||
NewFiles.Add(fileName, data);
|
{
|
||||||
}
|
lock (NewFiles)
|
||||||
}
|
{
|
||||||
return true;
|
if (NewFiles.ContainsKey(fileName))
|
||||||
}
|
{
|
||||||
|
NewFiles[fileName] = data;
|
||||||
|
}
|
||||||
public class XferDownLoad
|
else
|
||||||
{
|
{
|
||||||
public byte[] Data = new byte[0];
|
NewFiles.Add(fileName, data);
|
||||||
public string FileName = "";
|
}
|
||||||
public ulong XferID = 0;
|
}
|
||||||
public int DataPointer = 0;
|
return true;
|
||||||
public uint Packet = 0;
|
}
|
||||||
public IClientAPI Client;
|
|
||||||
public uint Serial = 1;
|
|
||||||
private bool complete = false;
|
public class XferDownLoad
|
||||||
|
{
|
||||||
public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
|
public byte[] Data = new byte[0];
|
||||||
{
|
public string FileName = String.Empty;
|
||||||
FileName = fileName;
|
public ulong XferID = 0;
|
||||||
Data = data;
|
public int DataPointer = 0;
|
||||||
XferID = xferID;
|
public uint Packet = 0;
|
||||||
Client = client;
|
public IClientAPI Client;
|
||||||
}
|
public uint Serial = 1;
|
||||||
|
private bool complete;
|
||||||
public XferDownLoad()
|
|
||||||
{
|
public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
|
||||||
}
|
{
|
||||||
|
FileName = fileName;
|
||||||
public void StartSend()
|
Data = data;
|
||||||
{
|
XferID = xferID;
|
||||||
if (Data.Length < 1000)
|
Client = client;
|
||||||
{
|
}
|
||||||
// for now (testing ) we only support files under 1000 bytes
|
|
||||||
byte[] transferData = new byte[Data.Length + 4];
|
public XferDownLoad()
|
||||||
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;
|
/// <summary>
|
||||||
}
|
/// Start a transfer
|
||||||
else
|
/// </summary>
|
||||||
{
|
/// <returns>True if the transfer is complete, false if not</returns>
|
||||||
byte[] transferData = new byte[1000 + 4];
|
public bool StartSend()
|
||||||
Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
|
{
|
||||||
Array.Copy(Data, 0, transferData, 4, 1000);
|
if (Data.Length < 1000)
|
||||||
Client.SendXferPacket(XferID, 0, transferData);
|
{
|
||||||
Packet++;
|
// for now (testing ) we only support files under 1000 bytes
|
||||||
DataPointer = 1000;
|
byte[] transferData = new byte[Data.Length + 4];
|
||||||
}
|
Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
|
||||||
}
|
Array.Copy(Data, 0, transferData, 4, Data.Length);
|
||||||
|
Client.SendXferPacket(XferID, 0 + 0x80000000, transferData);
|
||||||
public void AckPacket(uint packet)
|
|
||||||
{
|
complete = true;
|
||||||
if (!complete)
|
}
|
||||||
{
|
else
|
||||||
if ((Data.Length - DataPointer) > 1000)
|
{
|
||||||
{
|
byte[] transferData = new byte[1000 + 4];
|
||||||
byte[] transferData = new byte[1000];
|
Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4);
|
||||||
Array.Copy(Data, DataPointer, transferData, 0, 1000);
|
Array.Copy(Data, 0, transferData, 4, 1000);
|
||||||
Client.SendXferPacket(XferID, Packet, transferData);
|
Client.SendXferPacket(XferID, 0, transferData);
|
||||||
Packet++;
|
Packet++;
|
||||||
DataPointer += 1000;
|
DataPointer = 1000;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return complete;
|
||||||
byte[] transferData = new byte[Data.Length - DataPointer];
|
}
|
||||||
Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer);
|
|
||||||
uint endPacket = Packet |= (uint) 0x80000000;
|
/// <summary>
|
||||||
Client.SendXferPacket(XferID, endPacket, transferData);
|
/// Respond to an ack packet from the client
|
||||||
Packet++;
|
/// </summary>
|
||||||
DataPointer += (Data.Length - DataPointer);
|
/// <param name="packet"></param>
|
||||||
complete = true;
|
/// <returns>True if the transfer is complete, false otherwise</returns>
|
||||||
}
|
public bool AckPacket(uint packet)
|
||||||
}
|
{
|
||||||
}
|
if (!complete)
|
||||||
}
|
{
|
||||||
}
|
if ((Data.Length - DataPointer) > 1000)
|
||||||
}
|
{
|
||||||
|
byte[] transferData = new byte[1000];
|
||||||
|
Array.Copy(Data, DataPointer, transferData, 0, 1000);
|
||||||
|
Client.SendXferPacket(XferID, Packet, transferData);
|
||||||
|
Packet++;
|
||||||
|
DataPointer += 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte[] transferData = new byte[Data.Length - DataPointer];
|
||||||
|
Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer);
|
||||||
|
uint endPacket = Packet |= (uint) 0x80000000;
|
||||||
|
Client.SendXferPacket(XferID, endPacket, transferData);
|
||||||
|
Packet++;
|
||||||
|
DataPointer += (Data.Length - DataPointer);
|
||||||
|
|
||||||
|
complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue