Merge branch 'master' into careminster-presence-refactor
commit
47cf9c8fe0
|
@ -2304,6 +2304,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||||
/// <description>UUID of the region</description></item>
|
/// <description>UUID of the region</description></item>
|
||||||
/// <item><term>region_name</term>
|
/// <item><term>region_name</term>
|
||||||
/// <description>region name</description></item>
|
/// <description>region name</description></item>
|
||||||
|
/// <item><term>merge</term>
|
||||||
|
/// <description>true if oar should be merged</description></item>
|
||||||
|
/// <item><term>skip-assets</term>
|
||||||
|
/// <description>true if assets should be skiped</description></item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
/// <code>region_uuid</code> takes precedence over
|
/// <code>region_uuid</code> takes precedence over
|
||||||
|
@ -2362,10 +2366,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||||
throw new Exception(String.Format("failed to switch to region {0}", region_name));
|
throw new Exception(String.Format("failed to switch to region {0}", region_name));
|
||||||
}
|
}
|
||||||
else throw new Exception("neither region_name nor region_uuid given");
|
else throw new Exception("neither region_name nor region_uuid given");
|
||||||
|
|
||||||
|
bool mergeOar = false;
|
||||||
|
bool skipAssets = false;
|
||||||
|
|
||||||
|
if ((string)requestData["merge"] == "true")
|
||||||
|
{
|
||||||
|
mergeOar = true;
|
||||||
|
}
|
||||||
|
if ((string)requestData["skip-assets"] == "true")
|
||||||
|
{
|
||||||
|
skipAssets = true;
|
||||||
|
}
|
||||||
|
|
||||||
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
|
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
|
||||||
if (archiver != null)
|
if (archiver != null)
|
||||||
archiver.DearchiveRegion(filename);
|
archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty);
|
||||||
else
|
else
|
||||||
throw new Exception("Archiver module not present for scene");
|
throw new Exception("Archiver module not present for scene");
|
||||||
|
|
||||||
|
@ -2405,6 +2421,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||||
/// <description>UUID of the region</description></item>
|
/// <description>UUID of the region</description></item>
|
||||||
/// <item><term>region_name</term>
|
/// <item><term>region_name</term>
|
||||||
/// <description>region name</description></item>
|
/// <description>region name</description></item>
|
||||||
|
/// <item><term>profile</term>
|
||||||
|
/// <description>profile url</description></item>
|
||||||
|
/// <item><term>noassets</term>
|
||||||
|
/// <description>true if no assets should be saved</description></item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
/// <code>region_uuid</code> takes precedence over
|
/// <code>region_uuid</code> takes precedence over
|
||||||
|
@ -2462,12 +2482,29 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||||
}
|
}
|
||||||
else throw new Exception("neither region_name nor region_uuid given");
|
else throw new Exception("neither region_name nor region_uuid given");
|
||||||
|
|
||||||
|
Dictionary<string, object> options = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
//if (requestData.Contains("version"))
|
||||||
|
//{
|
||||||
|
// options["version"] = (string)requestData["version"];
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (requestData.Contains("profile"))
|
||||||
|
{
|
||||||
|
options["profile"] = (string)requestData["profile"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestData["noassets"] == "true")
|
||||||
|
{
|
||||||
|
options["noassets"] = (string)requestData["noassets"] ;
|
||||||
|
}
|
||||||
|
|
||||||
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
|
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
|
||||||
|
|
||||||
if (archiver != null)
|
if (archiver != null)
|
||||||
{
|
{
|
||||||
scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted;
|
scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted;
|
||||||
archiver.ArchiveRegion(filename, new Dictionary<string, object>());
|
archiver.ArchiveRegion(filename, options);
|
||||||
lock (m_saveOarLock) Monitor.Wait(m_saveOarLock,5000);
|
lock (m_saveOarLock) Monitor.Wait(m_saveOarLock,5000);
|
||||||
scene.EventManager.OnOarFileSaved -= RemoteAdminOarSaveCompleted;
|
scene.EventManager.OnOarFileSaved -= RemoteAdminOarSaveCompleted;
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,6 +281,7 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
UUID uuid = UUID.Zero;
|
UUID uuid = UUID.Zero;
|
||||||
|
|
|
@ -741,7 +741,7 @@ namespace OpenSim.Framework
|
||||||
bool IsActive { get; set; }
|
bool IsActive { get; set; }
|
||||||
|
|
||||||
/// <value>
|
/// <value>
|
||||||
/// Determines whether the client is logging out or not.
|
/// Determines whether the client is or has been removed from a given scene
|
||||||
/// </value>
|
/// </value>
|
||||||
bool IsLoggingOut { get; set; }
|
bool IsLoggingOut { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
@ -124,7 +125,6 @@ namespace OpenSim.Framework.Servers
|
||||||
m_logFileAppender = appender;
|
m_logFileAppender = appender;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -443,45 +443,68 @@ namespace OpenSim.Framework.Servers
|
||||||
{
|
{
|
||||||
string buildVersion = string.Empty;
|
string buildVersion = string.Empty;
|
||||||
|
|
||||||
// Add commit hash and date information if available
|
|
||||||
// The commit hash and date are stored in a file bin/.version
|
|
||||||
// This file can automatically created by a post
|
|
||||||
// commit script in the opensim git master repository or
|
|
||||||
// by issuing the follwoing command from the top level
|
|
||||||
// directory of the opensim repository
|
|
||||||
// git log -n 1 --pretty="format:%h: %ci" >bin/.version
|
|
||||||
// For the full git commit hash use %H instead of %h
|
|
||||||
//
|
|
||||||
// The subversion information is deprecated and will be removed at a later date
|
// The subversion information is deprecated and will be removed at a later date
|
||||||
// Add subversion revision information if available
|
// Add subversion revision information if available
|
||||||
// Try file "svn_revision" in the current directory first, then the .svn info.
|
// Try file "svn_revision" in the current directory first, then the .svn info.
|
||||||
// This allows to make the revision available in simulators not running from the source tree.
|
// This allows to make the revision available in simulators not running from the source tree.
|
||||||
// FIXME: Making an assumption about the directory we're currently in - we do this all over the place
|
// FIXME: Making an assumption about the directory we're currently in - we do this all over the place
|
||||||
// elsewhere as well
|
// elsewhere as well
|
||||||
|
string gitDir = "../.git/";
|
||||||
|
string gitRefPointerPath = gitDir + "HEAD";
|
||||||
|
|
||||||
string svnRevisionFileName = "svn_revision";
|
string svnRevisionFileName = "svn_revision";
|
||||||
string svnFileName = ".svn/entries";
|
string svnFileName = ".svn/entries";
|
||||||
string gitCommitFileName = ".version";
|
string manualVersionFileName = ".version";
|
||||||
string inputLine;
|
string inputLine;
|
||||||
int strcmp;
|
int strcmp;
|
||||||
|
|
||||||
if (File.Exists(gitCommitFileName))
|
if (File.Exists(manualVersionFileName))
|
||||||
{
|
{
|
||||||
StreamReader CommitFile = File.OpenText(gitCommitFileName);
|
using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
|
||||||
buildVersion = CommitFile.ReadLine();
|
buildVersion = CommitFile.ReadLine();
|
||||||
CommitFile.Close();
|
|
||||||
m_version += buildVersion ?? "";
|
m_version += buildVersion ?? "";
|
||||||
}
|
}
|
||||||
|
else if (File.Exists(gitRefPointerPath))
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[OPENSIM]: Found {0}", gitRefPointerPath);
|
||||||
|
|
||||||
// Remove the else logic when subversion mirror is no longer used
|
string rawPointer = "";
|
||||||
|
|
||||||
|
using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
|
||||||
|
rawPointer = pointerFile.ReadLine();
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[OPENSIM]: rawPointer [{0}]", rawPointer);
|
||||||
|
|
||||||
|
Match m = Regex.Match(rawPointer, "^ref: (.+)$");
|
||||||
|
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[OPENSIM]: Matched [{0}]", m.Groups[1].Value);
|
||||||
|
|
||||||
|
string gitRef = m.Groups[1].Value;
|
||||||
|
string gitRefPath = gitDir + gitRef;
|
||||||
|
if (File.Exists(gitRefPath))
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[OPENSIM]: Found gitRefPath [{0}]", gitRefPath);
|
||||||
|
|
||||||
|
using (StreamReader refFile = File.OpenText(gitRefPath))
|
||||||
|
{
|
||||||
|
string gitHash = refFile.ReadLine();
|
||||||
|
m_version += gitHash.Substring(0, 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Remove the else logic when subversion mirror is no longer used
|
||||||
if (File.Exists(svnRevisionFileName))
|
if (File.Exists(svnRevisionFileName))
|
||||||
{
|
{
|
||||||
StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
|
StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
|
||||||
buildVersion = RevisionFile.ReadLine();
|
buildVersion = RevisionFile.ReadLine();
|
||||||
buildVersion.Trim();
|
buildVersion.Trim();
|
||||||
RevisionFile.Close();
|
RevisionFile.Close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
|
if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
|
||||||
|
|
|
@ -328,7 +328,7 @@ namespace OpenSim
|
||||||
config.Set("meshing", "Meshmerizer");
|
config.Set("meshing", "Meshmerizer");
|
||||||
config.Set("physical_prim", true);
|
config.Set("physical_prim", true);
|
||||||
config.Set("see_into_this_sim_from_neighbor", true);
|
config.Set("see_into_this_sim_from_neighbor", true);
|
||||||
config.Set("serverside_object_permissions", false);
|
config.Set("serverside_object_permissions", true);
|
||||||
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
||||||
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
||||||
config.Set("storage_prim_inventories", true);
|
config.Set("storage_prim_inventories", true);
|
||||||
|
|
|
@ -86,6 +86,8 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
private List<string> m_CurrentlyWriting = new List<string>();
|
private List<string> m_CurrentlyWriting = new List<string>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
private bool m_FileCacheEnabled = true;
|
||||||
|
|
||||||
private ExpiringCache<string, AssetBase> m_MemoryCache;
|
private ExpiringCache<string, AssetBase> m_MemoryCache;
|
||||||
private bool m_MemoryCacheEnabled = false;
|
private bool m_MemoryCacheEnabled = false;
|
||||||
|
|
||||||
|
@ -146,6 +148,7 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
m_FileCacheEnabled = assetConfig.GetBoolean("FileCacheEnabled", m_FileCacheEnabled);
|
||||||
m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory);
|
m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory);
|
||||||
|
|
||||||
m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
|
m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
|
||||||
|
@ -173,7 +176,7 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
|
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
|
||||||
|
|
||||||
if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
|
if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
|
||||||
{
|
{
|
||||||
m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
|
m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
|
||||||
m_CacheCleanTimer.AutoReset = true;
|
m_CacheCleanTimer.AutoReset = true;
|
||||||
|
@ -226,7 +229,6 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
if (m_AssetService == null)
|
if (m_AssetService == null)
|
||||||
{
|
{
|
||||||
m_AssetService = scene.RequestModuleInterface<IAssetService>();
|
m_AssetService = scene.RequestModuleInterface<IAssetService>();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,18 +252,15 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
|
|
||||||
private void UpdateMemoryCache(string key, AssetBase asset)
|
private void UpdateMemoryCache(string key, AssetBase asset)
|
||||||
{
|
{
|
||||||
if (m_MemoryCacheEnabled)
|
m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
|
||||||
m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Cache(AssetBase asset)
|
private void UpdateFileCache(string key, AssetBase asset)
|
||||||
{
|
{
|
||||||
// TODO: Spawn this off to some seperate thread to do the actual writing
|
// TODO: Spawn this off to some seperate thread to do the actual writing
|
||||||
if (asset != null)
|
if (asset != null)
|
||||||
{
|
{
|
||||||
UpdateMemoryCache(asset.ID, asset);
|
string filename = GetFileName(key);
|
||||||
|
|
||||||
string filename = GetFileName(asset.ID);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -278,8 +277,8 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Once we start writing, make sure we flag that we're writing
|
// Once we start writing, make sure we flag that we're writing
|
||||||
// that object to the cache so that we don't try to write the
|
// that object to the cache so that we don't try to write the
|
||||||
// same file multiple times.
|
// same file multiple times.
|
||||||
|
@ -319,78 +318,118 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Cache(AssetBase asset)
|
||||||
|
{
|
||||||
|
// TODO: Spawn this off to some seperate thread to do the actual writing
|
||||||
|
if (asset != null)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
|
||||||
|
|
||||||
|
if (m_MemoryCacheEnabled)
|
||||||
|
UpdateMemoryCache(asset.ID, asset);
|
||||||
|
|
||||||
|
if (m_FileCacheEnabled)
|
||||||
|
UpdateFileCache(asset.ID, asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get an asset from the in-memory cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private AssetBase GetFromMemoryCache(string id)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
|
||||||
|
if (m_MemoryCache.TryGetValue(id, out asset))
|
||||||
|
m_MemoryHits++;
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get an asset from the file cache.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private AssetBase GetFromFileCache(string id)
|
||||||
|
{
|
||||||
|
AssetBase asset = null;
|
||||||
|
|
||||||
|
string filename = GetFileName(id);
|
||||||
|
if (File.Exists(filename))
|
||||||
|
{
|
||||||
|
FileStream stream = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
BinaryFormatter bformatter = new BinaryFormatter();
|
||||||
|
|
||||||
|
asset = (AssetBase)bformatter.Deserialize(stream);
|
||||||
|
|
||||||
|
UpdateMemoryCache(id, asset);
|
||||||
|
|
||||||
|
m_DiskHits++;
|
||||||
|
}
|
||||||
|
catch (System.Runtime.Serialization.SerializationException e)
|
||||||
|
{
|
||||||
|
LogException(e);
|
||||||
|
|
||||||
|
// If there was a problem deserializing the asset, the asset may
|
||||||
|
// either be corrupted OR was serialized under an old format
|
||||||
|
// {different version of AssetBase} -- we should attempt to
|
||||||
|
// delete it and re-cache
|
||||||
|
File.Delete(filename);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LogException(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (stream != null)
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if WAIT_ON_INPROGRESS_REQUESTS
|
||||||
|
// Check if we're already downloading this asset. If so, try to wait for it to
|
||||||
|
// download.
|
||||||
|
if (m_WaitOnInprogressTimeout > 0)
|
||||||
|
{
|
||||||
|
m_RequestsForInprogress++;
|
||||||
|
|
||||||
|
ManualResetEvent waitEvent;
|
||||||
|
if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
|
||||||
|
{
|
||||||
|
waitEvent.WaitOne(m_WaitOnInprogressTimeout);
|
||||||
|
return Get(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Track how often we have the problem that an asset is requested while
|
||||||
|
// it is still being downloaded by a previous request.
|
||||||
|
if (m_CurrentlyWriting.Contains(filename))
|
||||||
|
{
|
||||||
|
m_RequestsForInprogress++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
public AssetBase Get(string id)
|
public AssetBase Get(string id)
|
||||||
{
|
{
|
||||||
m_Requests++;
|
m_Requests++;
|
||||||
|
|
||||||
AssetBase asset = null;
|
AssetBase asset = null;
|
||||||
|
|
||||||
if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset))
|
if (m_MemoryCacheEnabled)
|
||||||
{
|
asset = GetFromMemoryCache(id);
|
||||||
m_MemoryHits++;
|
else if (m_FileCacheEnabled)
|
||||||
}
|
asset = GetFromFileCache(id);
|
||||||
else
|
|
||||||
{
|
|
||||||
string filename = GetFileName(id);
|
|
||||||
if (File.Exists(filename))
|
|
||||||
{
|
|
||||||
FileStream stream = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
BinaryFormatter bformatter = new BinaryFormatter();
|
|
||||||
|
|
||||||
asset = (AssetBase)bformatter.Deserialize(stream);
|
|
||||||
|
|
||||||
UpdateMemoryCache(id, asset);
|
|
||||||
|
|
||||||
m_DiskHits++;
|
|
||||||
}
|
|
||||||
catch (System.Runtime.Serialization.SerializationException e)
|
|
||||||
{
|
|
||||||
LogException(e);
|
|
||||||
|
|
||||||
// If there was a problem deserializing the asset, the asset may
|
|
||||||
// either be corrupted OR was serialized under an old format
|
|
||||||
// {different version of AssetBase} -- we should attempt to
|
|
||||||
// delete it and re-cache
|
|
||||||
File.Delete(filename);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
LogException(e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (stream != null)
|
|
||||||
stream.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if WAIT_ON_INPROGRESS_REQUESTS
|
|
||||||
// Check if we're already downloading this asset. If so, try to wait for it to
|
|
||||||
// download.
|
|
||||||
if (m_WaitOnInprogressTimeout > 0)
|
|
||||||
{
|
|
||||||
m_RequestsForInprogress++;
|
|
||||||
|
|
||||||
ManualResetEvent waitEvent;
|
|
||||||
if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
|
|
||||||
{
|
|
||||||
waitEvent.WaitOne(m_WaitOnInprogressTimeout);
|
|
||||||
return Get(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Track how often we have the problem that an asset is requested while
|
|
||||||
// it is still being downloaded by a previous request.
|
|
||||||
if (m_CurrentlyWriting.Contains(filename))
|
|
||||||
{
|
|
||||||
m_RequestsForInprogress++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
|
if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
|
||||||
{
|
{
|
||||||
|
@ -424,10 +463,13 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string filename = GetFileName(id);
|
if (m_FileCacheEnabled)
|
||||||
if (File.Exists(filename))
|
|
||||||
{
|
{
|
||||||
File.Delete(filename);
|
string filename = GetFileName(id);
|
||||||
|
if (File.Exists(filename))
|
||||||
|
{
|
||||||
|
File.Delete(filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_MemoryCacheEnabled)
|
if (m_MemoryCacheEnabled)
|
||||||
|
@ -442,11 +484,14 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
if (m_LogLevel >= 2)
|
if (m_LogLevel >= 2)
|
||||||
m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing Cache.");
|
m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches.");
|
||||||
|
|
||||||
foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
|
if (m_FileCacheEnabled)
|
||||||
{
|
{
|
||||||
Directory.Delete(dir);
|
foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
|
||||||
|
{
|
||||||
|
Directory.Delete(dir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_MemoryCacheEnabled)
|
if (m_MemoryCacheEnabled)
|
||||||
|
@ -481,9 +526,9 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
/// removes empty tier directories.
|
/// removes empty tier directories.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dir"></param>
|
/// <param name="dir"></param>
|
||||||
|
/// <param name="purgeLine"></param>
|
||||||
private void CleanExpiredFiles(string dir, DateTime purgeLine)
|
private void CleanExpiredFiles(string dir, DateTime purgeLine)
|
||||||
{
|
{
|
||||||
|
|
||||||
foreach (string file in Directory.GetFiles(dir))
|
foreach (string file in Directory.GetFiles(dir))
|
||||||
{
|
{
|
||||||
if (File.GetLastAccessTime(file) < purgeLine)
|
if (File.GetLastAccessTime(file) < purgeLine)
|
||||||
|
@ -721,18 +766,28 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case "status":
|
case "status":
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache : {0} assets", m_MemoryCache.Count);
|
if (m_MemoryCacheEnabled)
|
||||||
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count);
|
||||||
|
else
|
||||||
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled");
|
||||||
|
|
||||||
int fileCount = GetFileCacheCount(m_CacheDirectory);
|
if (m_FileCacheEnabled)
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] File Cache : {0} assets", fileCount);
|
|
||||||
|
|
||||||
foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
|
|
||||||
{
|
{
|
||||||
m_log.Info("[FLOTSAM ASSET CACHE] Deep Scans were performed on the following regions:");
|
int fileCount = GetFileCacheCount(m_CacheDirectory);
|
||||||
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount);
|
||||||
string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
|
|
||||||
DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
|
foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
|
{
|
||||||
|
m_log.Info("[FLOTSAM ASSET CACHE]: Deep Scans were performed on the following regions:");
|
||||||
|
|
||||||
|
string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
|
||||||
|
DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
|
||||||
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -740,7 +795,7 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
case "clear":
|
case "clear":
|
||||||
if (cmdparams.Length < 2)
|
if (cmdparams.Length < 2)
|
||||||
{
|
{
|
||||||
m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]");
|
m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,36 +816,48 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
|
|
||||||
if (clearMemory)
|
if (clearMemory)
|
||||||
{
|
{
|
||||||
m_MemoryCache.Clear();
|
if (m_MemoryCacheEnabled)
|
||||||
m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared.");
|
{
|
||||||
|
m_MemoryCache.Clear();
|
||||||
|
m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clearFile)
|
if (clearFile)
|
||||||
{
|
{
|
||||||
ClearFileCache();
|
if (m_FileCacheEnabled)
|
||||||
m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared.");
|
{
|
||||||
|
ClearFileCache();
|
||||||
|
m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case "assets":
|
case "assets":
|
||||||
m_log.Info("[FLOTSAM ASSET CACHE] Caching all assets, in all scenes.");
|
m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
|
||||||
|
|
||||||
Util.FireAndForget(delegate {
|
Util.FireAndForget(delegate {
|
||||||
int assetsCached = CacheScenes();
|
int assetsCached = CacheScenes();
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] Completed Scene Caching, {0} assets found.", assetsCached);
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "expire":
|
case "expire":
|
||||||
|
|
||||||
|
|
||||||
if (cmdparams.Length < 3)
|
if (cmdparams.Length < 3)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] Invalid parameters for Expire, please specify a valid date & time", cmd);
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,26 +875,28 @@ namespace Flotsam.RegionModules.AssetCache
|
||||||
|
|
||||||
if (!DateTime.TryParse(s_expirationDate, out expirationDate))
|
if (!DateTime.TryParse(s_expirationDate, out expirationDate))
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] {0} is not a valid date & time", cmd);
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CleanExpiredFiles(m_CacheDirectory, expirationDate);
|
if (m_FileCacheEnabled)
|
||||||
|
CleanExpiredFiles(m_CacheDirectory, expirationDate);
|
||||||
|
else
|
||||||
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing.");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] Unknown command {0}", cmd);
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmdparams.Length == 1)
|
else if (cmdparams.Length == 1)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache status - Display cache status");
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status");
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearmem - Remove all assets cached in memory");
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory");
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearfile - Remove all assets cached on disk");
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk");
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache cachescenes - Attempt a deep cache of all assets in all scenes");
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes");
|
||||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache <datetime> - Purge assets older then the specified date & time");
|
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net.Config;
|
||||||
|
using Nini.Config;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.Assets;
|
||||||
|
using Flotsam.RegionModules.AssetCache;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
|
using OpenSim.Tests.Common.Mock;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.CoreModules.Asset.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class FlotsamAssetCacheTests
|
||||||
|
{
|
||||||
|
protected TestScene m_scene;
|
||||||
|
protected FlotsamAssetCache m_cache;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
IConfigSource config = new IniConfigSource();
|
||||||
|
|
||||||
|
config.AddConfig("Modules");
|
||||||
|
config.Configs["Modules"].Set("AssetCaching", "FlotsamAssetCache");
|
||||||
|
config.AddConfig("AssetCache");
|
||||||
|
config.Configs["AssetCache"].Set("FileCacheEnabled", "false");
|
||||||
|
config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true");
|
||||||
|
|
||||||
|
m_cache = new FlotsamAssetCache();
|
||||||
|
m_scene = SceneSetupHelpers.SetupScene();
|
||||||
|
SceneSetupHelpers.SetupSceneModules(m_scene, config, m_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCacheAsset()
|
||||||
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
// log4net.Config.XmlConfigurator.Configure();
|
||||||
|
|
||||||
|
AssetBase asset = AssetHelpers.CreateAsset();
|
||||||
|
asset.ID = TestHelper.ParseTail(0x1).ToString();
|
||||||
|
|
||||||
|
// Check we don't get anything before the asset is put in the cache
|
||||||
|
AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
|
||||||
|
Assert.That(retrievedAsset, Is.Null);
|
||||||
|
|
||||||
|
m_cache.Store(asset);
|
||||||
|
|
||||||
|
// Check that asset is now in cache
|
||||||
|
retrievedAsset = m_cache.Get(asset.ID.ToString());
|
||||||
|
Assert.That(retrievedAsset, Is.Not.Null);
|
||||||
|
Assert.That(retrievedAsset.ID, Is.EqualTo(asset.ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExpireAsset()
|
||||||
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
// log4net.Config.XmlConfigurator.Configure();
|
||||||
|
|
||||||
|
AssetBase asset = AssetHelpers.CreateAsset();
|
||||||
|
asset.ID = TestHelper.ParseTail(0x2).ToString();
|
||||||
|
|
||||||
|
m_cache.Store(asset);
|
||||||
|
|
||||||
|
m_cache.Expire(asset.ID);
|
||||||
|
|
||||||
|
AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
|
||||||
|
Assert.That(retrievedAsset, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestClearCache()
|
||||||
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
// log4net.Config.XmlConfigurator.Configure();
|
||||||
|
|
||||||
|
AssetBase asset = AssetHelpers.CreateAsset();
|
||||||
|
asset.ID = TestHelper.ParseTail(0x2).ToString();
|
||||||
|
|
||||||
|
m_cache.Store(asset);
|
||||||
|
|
||||||
|
m_cache.Clear();
|
||||||
|
|
||||||
|
AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString());
|
||||||
|
Assert.That(retrievedAsset, Is.Null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -449,7 +449,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
|
|
||||||
public bool IsBannedFromLand(UUID avatar)
|
public bool IsBannedFromLand(UUID avatar)
|
||||||
{
|
{
|
||||||
if (m_scene.Permissions.IsAdministrator(avatar))
|
if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
|
if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
|
||||||
|
@ -463,7 +463,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
if (e.AgentID == avatar && e.Flags == AccessList.Ban)
|
if (e.AgentID == avatar && e.Flags == AccessList.Ban)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}) != -1 && LandData.OwnerID != avatar)
|
}) != -1)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -473,7 +473,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
|
|
||||||
public bool IsRestrictedFromLand(UUID avatar)
|
public bool IsRestrictedFromLand(UUID avatar)
|
||||||
{
|
{
|
||||||
if (m_scene.Permissions.IsAdministrator(avatar))
|
if (m_scene.Permissions.CanEditParcelProperties(avatar, this, 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
|
if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar))
|
||||||
|
@ -487,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
if (e.AgentID == avatar && e.Flags == AccessList.Access)
|
if (e.AgentID == avatar && e.Flags == AccessList.Access)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}) == -1 && LandData.OwnerID != avatar)
|
}) == -1)
|
||||||
{
|
{
|
||||||
if (!HasGroupAccess(avatar))
|
if (!HasGroupAccess(avatar))
|
||||||
{
|
{
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false);
|
m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false);
|
||||||
m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", false);
|
m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true);
|
||||||
m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true);
|
m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true);
|
||||||
m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true);
|
m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true);
|
||||||
m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false);
|
m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.Avatar.NPC
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
{
|
{
|
||||||
public interface INPCModule
|
public interface INPCModule
|
||||||
{
|
{
|
|
@ -0,0 +1,156 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Scenes
|
||||||
|
{
|
||||||
|
class FetchHolder
|
||||||
|
{
|
||||||
|
public IClientAPI Client { get; private set; }
|
||||||
|
public UUID ItemID { get; private set; }
|
||||||
|
|
||||||
|
public FetchHolder(IClientAPI client, UUID itemID)
|
||||||
|
{
|
||||||
|
Client = client;
|
||||||
|
ItemID = itemID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send FetchInventoryReply information to clients asynchronously on a single thread rather than asynchronously via
|
||||||
|
/// multiple threads.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the main root inventory is right-clicked on a version 1 viewer for a user with a large inventory, a very
|
||||||
|
/// very large number of FetchInventory requests are sent to the simulator. Each is handled on a separate thread
|
||||||
|
/// by the IClientAPI, but the sheer number of requests overwhelms the number of threads available and ends up
|
||||||
|
/// freezing the inbound packet handling.
|
||||||
|
///
|
||||||
|
/// This class makes the first FetchInventory packet thread process the queue. If new requests come
|
||||||
|
/// in while it is processing, then the subsequent threads just add the requests and leave it to the original
|
||||||
|
/// thread to process them.
|
||||||
|
///
|
||||||
|
/// This might slow down outbound packets but these are limited by the IClientAPI outbound queues
|
||||||
|
/// anyway.
|
||||||
|
///
|
||||||
|
/// It might be possible to ignore FetchInventory requests altogether, particularly as they are redundant wrt to
|
||||||
|
/// FetchInventoryDescendents requests, but this would require more investigation.
|
||||||
|
/// </remarks>
|
||||||
|
public class AsyncInventorySender
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
protected Scene m_scene;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queues fetch requests
|
||||||
|
/// </summary>
|
||||||
|
Queue<FetchHolder> m_fetchHolder = new Queue<FetchHolder>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signal whether a queue is currently being processed or not.
|
||||||
|
/// </summary>
|
||||||
|
protected volatile bool m_processing;
|
||||||
|
|
||||||
|
public AsyncInventorySender(Scene scene)
|
||||||
|
{
|
||||||
|
m_processing = false;
|
||||||
|
m_scene = scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle a fetch inventory request from the client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="remoteClient"></param>
|
||||||
|
/// <param name="itemID"></param>
|
||||||
|
/// <param name="ownerID"></param>
|
||||||
|
public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
|
||||||
|
{
|
||||||
|
lock (m_fetchHolder)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[ASYNC INVENTORY SENDER]: Putting request from {0} for {1} on queue", remoteClient.Name, itemID);
|
||||||
|
|
||||||
|
m_fetchHolder.Enqueue(new FetchHolder(remoteClient, itemID));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_processing)
|
||||||
|
{
|
||||||
|
m_processing = true;
|
||||||
|
ProcessQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process the queue of fetches
|
||||||
|
/// </summary>
|
||||||
|
protected void ProcessQueue()
|
||||||
|
{
|
||||||
|
FetchHolder fh = null;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_fetchHolder)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[ASYNC INVENTORY SENDER]: {0} items left to process", m_fetchHolder.Count);
|
||||||
|
|
||||||
|
if (m_fetchHolder.Count == 0)
|
||||||
|
{
|
||||||
|
m_processing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fh = m_fetchHolder.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fh.Client.IsLoggingOut)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID);
|
||||||
|
|
||||||
|
InventoryItemBase item = new InventoryItemBase(fh.ItemID, fh.Client.AgentId);
|
||||||
|
item = m_scene.InventoryService.GetItem(item);
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
fh.Client.SendInventoryItemDetails(item.Owner, item);
|
||||||
|
|
||||||
|
// TODO: Possibly log any failure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;
|
protected AsyncSceneObjectGroupDeleter m_asyncSceneObjectDeleter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows inventory details to be sent to clients asynchronously
|
||||||
|
/// </summary>
|
||||||
|
protected AsyncInventorySender m_asyncInventorySender;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start all the scripts in the scene which should be started.
|
/// Start all the scripts in the scene which should be started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -461,31 +461,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handle a fetch inventory request from the client
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="remoteClient"></param>
|
|
||||||
/// <param name="itemID"></param>
|
|
||||||
/// <param name="ownerID"></param>
|
|
||||||
public void HandleFetchInventory(IClientAPI remoteClient, UUID itemID, UUID ownerID)
|
|
||||||
{
|
|
||||||
if (LibraryService != null && LibraryService.LibraryRootFolder != null && ownerID == LibraryService.LibraryRootFolder.Owner)
|
|
||||||
{
|
|
||||||
//m_log.Debug("request info for library item");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
|
|
||||||
item = InventoryService.GetItem(item);
|
|
||||||
|
|
||||||
if (item != null)
|
|
||||||
{
|
|
||||||
remoteClient.SendInventoryItemDetails(ownerID, item);
|
|
||||||
}
|
|
||||||
// else shouldn't we send an alert message?
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tell the client about the various child items and folders contained in the requested folder.
|
/// Tell the client about the various child items and folders contained in the requested folder.
|
||||||
|
|
|
@ -604,6 +604,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
|
m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
|
||||||
m_asyncSceneObjectDeleter.Enabled = true;
|
m_asyncSceneObjectDeleter.Enabled = true;
|
||||||
|
|
||||||
|
m_asyncInventorySender = new AsyncInventorySender(this);
|
||||||
|
|
||||||
#region Region Settings
|
#region Region Settings
|
||||||
|
|
||||||
// Load region settings
|
// Load region settings
|
||||||
|
@ -2866,14 +2868,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public virtual void SubscribeToClientInventoryEvents(IClientAPI client)
|
public virtual void SubscribeToClientInventoryEvents(IClientAPI client)
|
||||||
{
|
{
|
||||||
|
|
||||||
client.OnLinkInventoryItem += HandleLinkInventoryItem;
|
client.OnLinkInventoryItem += HandleLinkInventoryItem;
|
||||||
client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder;
|
client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder;
|
||||||
client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder;
|
client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder;
|
||||||
client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!!
|
client.OnMoveInventoryFolder += HandleMoveInventoryFolder; // 2; //!!
|
||||||
client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents;
|
client.OnFetchInventoryDescendents += HandleFetchInventoryDescendents;
|
||||||
client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!!
|
client.OnPurgeInventoryDescendents += HandlePurgeInventoryDescendents; // 2; //!!
|
||||||
client.OnFetchInventory += HandleFetchInventory;
|
client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
|
||||||
client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
|
client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
|
||||||
client.OnCopyInventoryItem += CopyInventoryItem;
|
client.OnCopyInventoryItem += CopyInventoryItem;
|
||||||
client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
|
client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
|
||||||
|
@ -2993,13 +2994,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client)
|
public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client)
|
||||||
{
|
{
|
||||||
|
|
||||||
client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder;
|
client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder;
|
||||||
client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder;
|
client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder;
|
||||||
client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!!
|
client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!!
|
||||||
client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents;
|
client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents;
|
||||||
client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!!
|
client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!!
|
||||||
client.OnFetchInventory -= HandleFetchInventory;
|
client.OnFetchInventory -= m_asyncInventorySender.HandleFetchInventory;
|
||||||
client.OnUpdateInventoryItem -= UpdateInventoryItemAsset;
|
client.OnUpdateInventoryItem -= UpdateInventoryItemAsset;
|
||||||
client.OnCopyInventoryItem -= CopyInventoryItem;
|
client.OnCopyInventoryItem -= CopyInventoryItem;
|
||||||
client.OnMoveInventoryItem -= MoveInventoryItem;
|
client.OnMoveInventoryItem -= MoveInventoryItem;
|
||||||
|
|
|
@ -34,7 +34,6 @@ using Nini.Config;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Region.CoreModules.Avatar.NPC;
|
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using Timer=System.Timers.Timer;
|
using Timer=System.Timers.Timer;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
|
@ -47,31 +46,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
|
|
||||||
// private const bool m_enabled = false;
|
// private const bool m_enabled = false;
|
||||||
|
|
||||||
private Mutex m_createMutex;
|
|
||||||
private Timer m_timer;
|
|
||||||
|
|
||||||
private Dictionary<UUID,NPCAvatar> m_avatars = new Dictionary<UUID, NPCAvatar>();
|
private Dictionary<UUID,NPCAvatar> m_avatars = new Dictionary<UUID, NPCAvatar>();
|
||||||
private Dictionary<UUID,AvatarAppearance> m_appearanceCache = new Dictionary<UUID, AvatarAppearance>();
|
private Dictionary<UUID,AvatarAppearance> m_appearanceCache = new Dictionary<UUID, AvatarAppearance>();
|
||||||
|
|
||||||
// Timer vars.
|
|
||||||
private bool p_inUse = false;
|
|
||||||
private readonly object p_lock = new object();
|
|
||||||
// Private Temporary Variables.
|
|
||||||
private string p_firstname;
|
|
||||||
private string p_lastname;
|
|
||||||
private Vector3 p_position;
|
|
||||||
private Scene p_scene;
|
|
||||||
private UUID p_cloneAppearanceFrom;
|
|
||||||
private UUID p_returnUuid;
|
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource source)
|
public void Initialise(Scene scene, IConfigSource source)
|
||||||
{
|
{
|
||||||
m_createMutex = new Mutex(false);
|
|
||||||
|
|
||||||
m_timer = new Timer(500);
|
|
||||||
m_timer.Elapsed += m_timer_Elapsed;
|
|
||||||
m_timer.Start();
|
|
||||||
|
|
||||||
scene.RegisterModuleInterface<INPCModule>(this);
|
scene.RegisterModuleInterface<INPCModule>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,35 +69,53 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
return new AvatarAppearance();
|
return new AvatarAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID CreateNPC(string firstname, string lastname,Vector3 position, Scene scene, UUID cloneAppearanceFrom)
|
public UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, UUID cloneAppearanceFrom)
|
||||||
{
|
{
|
||||||
|
NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene);
|
||||||
|
npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue);
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[NPC MODULE]: Queueing request to create NPC {0} {1} at {2} in {3} cloning appearance of {4}",
|
"[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}",
|
||||||
firstname, lastname, position, scene.RegionInfo.RegionName, cloneAppearanceFrom);
|
firstname, lastname, npcAvatar.AgentId, position, scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
// Block.
|
AgentCircuitData acd = new AgentCircuitData();
|
||||||
m_createMutex.WaitOne();
|
acd.AgentID = npcAvatar.AgentId;
|
||||||
|
acd.firstname = firstname;
|
||||||
|
acd.lastname = lastname;
|
||||||
|
acd.ServiceURLs = new Dictionary<string, object>();
|
||||||
|
|
||||||
// Copy Temp Variables for Timer to pick up.
|
AvatarAppearance originalAppearance = GetAppearance(cloneAppearanceFrom, scene);
|
||||||
lock (p_lock)
|
AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true);
|
||||||
|
acd.Appearance = npcAppearance;
|
||||||
|
|
||||||
|
scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
|
||||||
|
scene.AddNewClient(npcAvatar);
|
||||||
|
|
||||||
|
ScenePresence sp;
|
||||||
|
if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
|
||||||
{
|
{
|
||||||
p_firstname = firstname;
|
m_log.DebugFormat(
|
||||||
p_lastname = lastname;
|
"[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
|
||||||
p_position = position;
|
|
||||||
p_scene = scene;
|
// Shouldn't call this - temporary.
|
||||||
p_cloneAppearanceFrom = cloneAppearanceFrom;
|
sp.CompleteMovement(npcAvatar);
|
||||||
p_inUse = true;
|
|
||||||
p_returnUuid = UUID.Zero;
|
// sp.SendAppearanceToAllOtherAgents();
|
||||||
|
//
|
||||||
|
// // Send animations back to the avatar as well
|
||||||
|
// sp.Animator.SendAnimPack();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (p_returnUuid == UUID.Zero)
|
lock (m_avatars)
|
||||||
{
|
m_avatars.Add(npcAvatar.AgentId, npcAvatar);
|
||||||
Thread.Sleep(250);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_createMutex.ReleaseMutex();
|
m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId);
|
||||||
|
|
||||||
return p_returnUuid;
|
return npcAvatar.AgentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Autopilot(UUID agentID, Scene scene, Vector3 pos)
|
public void Autopilot(UUID agentID, Scene scene, Vector3 pos)
|
||||||
|
@ -157,69 +154,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lock (p_lock)
|
|
||||||
{
|
|
||||||
if (p_inUse)
|
|
||||||
{
|
|
||||||
p_inUse = false;
|
|
||||||
|
|
||||||
NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene);
|
|
||||||
npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue);
|
|
||||||
|
|
||||||
m_log.DebugFormat(
|
|
||||||
"[NPC MODULE]: Creating NPC {0} {1} {2} at {3} in {4}",
|
|
||||||
p_firstname, p_lastname, npcAvatar.AgentId, p_position, p_scene.RegionInfo.RegionName);
|
|
||||||
|
|
||||||
AgentCircuitData acd = new AgentCircuitData();
|
|
||||||
acd.AgentID = npcAvatar.AgentId;
|
|
||||||
acd.firstname = p_firstname;
|
|
||||||
acd.lastname = p_lastname;
|
|
||||||
acd.ServiceURLs = new Dictionary<string, object>();
|
|
||||||
|
|
||||||
AvatarAppearance originalAppearance = GetAppearance(p_cloneAppearanceFrom, p_scene);
|
|
||||||
AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true);
|
|
||||||
acd.Appearance = npcAppearance;
|
|
||||||
|
|
||||||
p_scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
|
|
||||||
p_scene.AddNewClient(npcAvatar);
|
|
||||||
|
|
||||||
ScenePresence sp;
|
|
||||||
if (p_scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
|
|
||||||
{
|
|
||||||
m_log.DebugFormat(
|
|
||||||
"[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
|
|
||||||
|
|
||||||
// Shouldn't call this - temporary.
|
|
||||||
sp.CompleteMovement(npcAvatar);
|
|
||||||
|
|
||||||
// sp.SendAppearanceToAllOtherAgents();
|
|
||||||
//
|
|
||||||
// // Send animations back to the avatar as well
|
|
||||||
// sp.Animator.SendAnimPack();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("[NPC MODULE]: Could not find scene presence for NPC {0} {1}", sp.Name, sp.UUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_avatars.Add(npcAvatar.AgentId, npcAvatar);
|
|
||||||
|
|
||||||
p_returnUuid = npcAvatar.AgentId;
|
|
||||||
|
|
||||||
m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", p_returnUuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
m_log.ErrorFormat("[NPC MODULE]: NPC creation failed with exception {0} {1}", ex.Message, ex.StackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -238,4 +172,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Communications;
|
||||||
|
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.AvatarService;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
|
using OpenSim.Tests.Common.Mock;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.OptionalModules.World.NPC.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class NPCModuleTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCreate()
|
||||||
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
// log4net.Config.XmlConfigurator.Configure();
|
||||||
|
|
||||||
|
IConfigSource config = new IniConfigSource();
|
||||||
|
|
||||||
|
config.AddConfig("Modules");
|
||||||
|
config.Configs["Modules"].Set("AvatarServices", "LocalAvatarServicesConnector");
|
||||||
|
config.AddConfig("AvatarService");
|
||||||
|
config.Configs["AvatarService"].Set("LocalServiceModule", "OpenSim.Services.AvatarService.dll:AvatarService");
|
||||||
|
config.Configs["AvatarService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
|
||||||
|
|
||||||
|
TestScene scene = SceneSetupHelpers.SetupScene();
|
||||||
|
SceneSetupHelpers.SetupSceneModules(scene, config, new NPCModule(), new LocalAvatarServicesConnector());
|
||||||
|
|
||||||
|
INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
|
||||||
|
UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, UUID.Zero);
|
||||||
|
|
||||||
|
ScenePresence npc = scene.GetScenePresence(npcId);
|
||||||
|
Assert.That(npc, Is.Not.Null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -291,7 +291,14 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data);
|
OSD osd = OSDParser.DeserializeLLSDBinary(data);
|
||||||
|
if (osd is OSDMap)
|
||||||
|
meshOsd = (OSDMap)osd;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -302,11 +309,17 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
if (meshOsd is OSDMap)
|
if (meshOsd is OSDMap)
|
||||||
{
|
{
|
||||||
|
OSDMap physicsParms = null;
|
||||||
OSDMap map = (OSDMap)meshOsd;
|
OSDMap map = (OSDMap)meshOsd;
|
||||||
OSDMap physicsParms = (OSDMap)map["physics_shape"]; // old asset format
|
if (map.ContainsKey("physics_shape"))
|
||||||
|
physicsParms = (OSDMap)map["physics_shape"]; // old asset format
|
||||||
if (physicsParms.Count == 0)
|
else if (map.ContainsKey("physics_mesh"))
|
||||||
physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
|
physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
|
||||||
|
if (physicsParms == null)
|
||||||
|
{
|
||||||
|
m_log.Warn("[Mesh]: no recognized physics mesh found in mesh asset");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
int physOffset = physicsParms["offset"].AsInteger() + (int)start;
|
int physOffset = physicsParms["offset"].AsInteger() + (int)start;
|
||||||
int physSize = physicsParms["size"].AsInteger();
|
int physSize = physicsParms["size"].AsInteger();
|
||||||
|
|
|
@ -2502,7 +2502,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
|
// if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
|
||||||
if (!forceSimplePrimMeshing)
|
if (!forceSimplePrimMeshing && !pbs.SculptEntry)
|
||||||
{
|
{
|
||||||
if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
|
if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
|
||||||
|| (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
|
|| (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
|
||||||
|
@ -2592,6 +2592,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pbs.SculptEntry && meshSculptedPrim)
|
||||||
|
iPropertiesNotSupportedDefault++;
|
||||||
|
|
||||||
|
|
||||||
if (iPropertiesNotSupportedDefault == 0)
|
if (iPropertiesNotSupportedDefault == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,7 +38,6 @@ using OpenSim;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
using OpenSim.Region.CoreModules.Avatar.NPC;
|
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Region.ScriptEngine.Shared;
|
using OpenSim.Region.ScriptEngine.Shared;
|
||||||
|
|
|
@ -36,6 +36,15 @@ namespace OpenSim.Tests.Common
|
||||||
{
|
{
|
||||||
public class AssetHelpers
|
public class AssetHelpers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Create a notecard asset with a random uuids and dummy text.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static AssetBase CreateAsset()
|
||||||
|
{
|
||||||
|
return CreateAsset(UUID.Random(), AssetType.Notecard, "hello", UUID.Random());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a notecard asset with a random uuid and dummy text.
|
/// Create a notecard asset with a random uuid and dummy text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Tests.Common
|
namespace OpenSim.Tests.Common
|
||||||
{
|
{
|
||||||
|
@ -56,5 +57,15 @@ namespace OpenSim.Tests.Common
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("===> In Test Method : {0} <===", stackTrace.GetFrame(1).GetMethod().Name);
|
Console.WriteLine("===> In Test Method : {0} <===", stackTrace.GetFrame(1).GetMethod().Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parse tail section into full UUID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tail"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static UUID ParseTail(int tail)
|
||||||
|
{
|
||||||
|
return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,7 @@ namespace OpenSim.Tools.Configger
|
||||||
config.Set("meshing", "Meshmerizer");
|
config.Set("meshing", "Meshmerizer");
|
||||||
config.Set("physical_prim", true);
|
config.Set("physical_prim", true);
|
||||||
config.Set("see_into_this_sim_from_neighbor", true);
|
config.Set("see_into_this_sim_from_neighbor", true);
|
||||||
config.Set("serverside_object_permissions", false);
|
config.Set("serverside_object_permissions", true);
|
||||||
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
||||||
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
||||||
config.Set("storage_prim_inventories", true);
|
config.Set("storage_prim_inventories", true);
|
||||||
|
|
|
@ -78,20 +78,19 @@
|
||||||
; DrawPrimOnMapTile = true
|
; DrawPrimOnMapTile = true
|
||||||
|
|
||||||
;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256
|
;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256
|
||||||
;; Maximum size for non-physical prims
|
;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
|
||||||
; NonPhysicalPrimMax = 256
|
; NonPhysicalPrimMax = 256
|
||||||
|
|
||||||
;# {PhysicalPrimMax} {} {Maximum size of physical prims?} {} 10
|
;# {PhysicalPrimMax} {} {Maximum size of physical prims?} {} 10
|
||||||
;; Maximum size where a prim can be physical
|
;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file.
|
||||||
; PhysicalPrimMax = 10
|
; PhysicalPrimMax = 10
|
||||||
|
|
||||||
;; Prevent the creation, import and rez of prims that exceed the
|
;; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
|
||||||
;; maximum size.
|
;; This can be overriden in the region config file.
|
||||||
; ClampPrimSize = false
|
; ClampPrimSize = false
|
||||||
|
|
||||||
;# {AllowScriptCrossing} {} {Allow scripts to cross into this region} {true false} false
|
;# {AllowScriptCrossing} {} {Allow scripts to cross into this region} {true false} false
|
||||||
;; Allow scripts to cross region boundaries. These are recompiled on the
|
;; Allow scripts to keep running when they cross region boundaries, rather than being restarted. Script code is recompiled on the destination region and the state reloaded.
|
||||||
;; new region.
|
|
||||||
; AllowScriptCrossing = false
|
; AllowScriptCrossing = false
|
||||||
|
|
||||||
;# {TrustBinaries} {AllowScriptCrossing:true} {Accept compiled binary script code? (DANGEROUS!)} {true false} false
|
;# {TrustBinaries} {AllowScriptCrossing:true} {Accept compiled binary script code? (DANGEROUS!)} {true false} false
|
||||||
|
@ -173,7 +172,7 @@
|
||||||
;; permission checks (allowing anybody to copy
|
;; permission checks (allowing anybody to copy
|
||||||
;; any item, etc. This may not yet be implemented uniformally.
|
;; any item, etc. This may not yet be implemented uniformally.
|
||||||
;; If set to true, then all permissions checks are carried out
|
;; If set to true, then all permissions checks are carried out
|
||||||
; serverside_object_permissions = false
|
; serverside_object_permissions = true
|
||||||
|
|
||||||
;; This allows users with a UserLevel of 200 or more to assume god
|
;; This allows users with a UserLevel of 200 or more to assume god
|
||||||
;; powers in the regions in this simulator.
|
;; powers in the regions in this simulator.
|
||||||
|
@ -292,28 +291,31 @@
|
||||||
;; building's lights to possibly not be rendered.
|
;; building's lights to possibly not be rendered.
|
||||||
; DisableFacelights = "false"
|
; DisableFacelights = "false"
|
||||||
|
|
||||||
|
|
||||||
[ClientStack.LindenCaps]
|
[ClientStack.LindenCaps]
|
||||||
;; For the long list of capabilities, see OpenSimDefaults.ini
|
;; For the long list of capabilities, see OpenSimDefaults.ini
|
||||||
;; Here are the few ones you may want to change. Possible values
|
;; Here are the few ones you may want to change. Possible values
|
||||||
;; are:
|
;; are:
|
||||||
;; "" -- empty, capability disabled
|
;; "" -- empty, capability disabled
|
||||||
;; "localhost" -- capability enabled and served by the simulator
|
;; "localhost" -- capability enabled and served by the simulator
|
||||||
;; "<url>" -- capability enabled and served by some other server
|
;; "<url>" -- capability enabled and served by some other server
|
||||||
;;
|
;;
|
||||||
; These are enabled by default to localhost. Change if you see fit.
|
; These are enabled by default to localhost. Change if you see fit.
|
||||||
Cap_GetTexture = "localhost"
|
Cap_GetTexture = "localhost"
|
||||||
Cap_GetMesh = "localhost"
|
Cap_GetMesh = "localhost"
|
||||||
; This is disabled by default. Change if you see fit. Note that
|
; This is disabled by default. Change if you see fit. Note that
|
||||||
; serving this cap from the simulators may lead to poor performace.
|
; serving this cap from the simulators may lead to poor performace.
|
||||||
Cap_WebFetchInventoryDescendents = ""
|
Cap_WebFetchInventoryDescendents = ""
|
||||||
|
|
||||||
|
|
||||||
[SimulatorFeatures]
|
[SimulatorFeatures]
|
||||||
; Experimental new information sent in SimulatorFeatures cap for Kokua viewers
|
; Experimental new information sent in SimulatorFeatures cap for Kokua viewers
|
||||||
; meant to override the MapImage and search server url given at login, and varying
|
; meant to override the MapImage and search server url given at login, and varying
|
||||||
; on a sim-basis.
|
; on a sim-basis.
|
||||||
; Viewers that don't understand it, will ignore it
|
; Viewers that don't understand it, will ignore it
|
||||||
;MapImageServerURI = "http://127.0.0.1:9000/
|
;MapImageServerURI = "http://127.0.0.1:9000/
|
||||||
;SearchServerURI = "http://127.0.0.1:9000/
|
;SearchServerURI = "http://127.0.0.1:9000/
|
||||||
|
|
||||||
|
|
||||||
[Chat]
|
[Chat]
|
||||||
;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10
|
;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10
|
||||||
|
@ -650,6 +652,7 @@
|
||||||
;; If using a remote connector, specify the server URL
|
;; If using a remote connector, specify the server URL
|
||||||
; FreeswitchServiceURL = http://my.grid.server:8004/fsapi
|
; FreeswitchServiceURL = http://my.grid.server:8004/fsapi
|
||||||
|
|
||||||
|
|
||||||
[Groups]
|
[Groups]
|
||||||
;# {Enabled} {} {Enable groups?} {true false} false
|
;# {Enabled} {} {Enable groups?} {true false} false
|
||||||
;; Enables the groups module
|
;; Enables the groups module
|
||||||
|
@ -707,11 +710,13 @@
|
||||||
;; Enable media on a prim facilities
|
;; Enable media on a prim facilities
|
||||||
; Enabled = true;
|
; Enabled = true;
|
||||||
|
|
||||||
|
|
||||||
[PrimLimitsModule]
|
[PrimLimitsModule]
|
||||||
;# {EnforcePrimLimits} {} {Enforce parcel prim limits} {true false} false
|
;# {EnforcePrimLimits} {} {Enforce parcel prim limits} {true false} false
|
||||||
;; Enable parcel prim limits. Off by default to emulate pre-existing behavior.
|
;; Enable parcel prim limits. Off by default to emulate pre-existing behavior.
|
||||||
; EnforcePrimLimits = false
|
; EnforcePrimLimits = false
|
||||||
|
|
||||||
|
|
||||||
[Architecture]
|
[Architecture]
|
||||||
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini config-include/SimianGrid.ini config-include/HyperSimianGrid.ini} config-include/Standalone.ini
|
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini config-include/SimianGrid.ini config-include/HyperSimianGrid.ini} config-include/Standalone.ini
|
||||||
;; Uncomment one of the following includes as required. For instance, to create a standalone OpenSim,
|
;; Uncomment one of the following includes as required. For instance, to create a standalone OpenSim,
|
||||||
|
|
|
@ -14,10 +14,13 @@
|
||||||
; Place to create a PID file
|
; Place to create a PID file
|
||||||
; PIDFile = "/tmp/my.pid"
|
; PIDFile = "/tmp/my.pid"
|
||||||
|
|
||||||
|
; Console commands run at startup
|
||||||
startup_console_commands_file = "startup_commands.txt"
|
startup_console_commands_file = "startup_commands.txt"
|
||||||
|
|
||||||
|
; Console commands run on shutdown
|
||||||
shutdown_console_commands_file = "shutdown_commands.txt"
|
shutdown_console_commands_file = "shutdown_commands.txt"
|
||||||
|
|
||||||
; To run a script every few minutes, set the script filename here
|
; Console commands run every 20 minutes
|
||||||
; timer_Script = "filename"
|
; timer_Script = "filename"
|
||||||
|
|
||||||
; ##
|
; ##
|
||||||
|
@ -70,12 +73,17 @@
|
||||||
; Use terrain texture for maptiles if true, use shaded green if false
|
; Use terrain texture for maptiles if true, use shaded green if false
|
||||||
TextureOnMapTile = false
|
TextureOnMapTile = false
|
||||||
|
|
||||||
; Maximum total size, and maximum size where a prim can be physical
|
; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
|
||||||
NonPhysicalPrimMax = 256
|
NonPhysicalPrimMax = 256
|
||||||
PhysicalPrimMax = 10 ; (I think this was moved to the Regions.ini!)
|
|
||||||
|
; Maximum size of physical prims. Affects resizing of existing prims. This can be overriden in the region config file.
|
||||||
|
PhysicalPrimMax = 10
|
||||||
|
|
||||||
|
; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
|
||||||
|
; This can be overriden in the region config file.
|
||||||
ClampPrimSize = false
|
ClampPrimSize = false
|
||||||
|
|
||||||
; Allow scripts to cross region boundaries. These are recompiled on the new region.
|
; Allow scripts to keep running when they cross region boundaries, rather than being restarted. Script code is recompiled on the destination region and the state reloaded.
|
||||||
AllowScriptCrossing = false
|
AllowScriptCrossing = false
|
||||||
|
|
||||||
; Allow compiled script binary code to cross region boundaries.
|
; Allow compiled script binary code to cross region boundaries.
|
||||||
|
@ -94,7 +102,7 @@
|
||||||
; neighbors on each side for a total of 49 regions in view. Warning, unless
|
; neighbors on each side for a total of 49 regions in view. Warning, unless
|
||||||
; all the regions have the same drawdistance, you will end up with strange
|
; all the regions have the same drawdistance, you will end up with strange
|
||||||
; effects because the agents that get closed may be inconsistent.
|
; effects because the agents that get closed may be inconsistent.
|
||||||
; DefaultDrawDistance = 255.0
|
DefaultDrawDistance = 255.0
|
||||||
|
|
||||||
; If you have only one region in an instance, or to avoid the many bugs
|
; If you have only one region in an instance, or to avoid the many bugs
|
||||||
; that you can trigger in modules by restarting a region, set this to
|
; that you can trigger in modules by restarting a region, set this to
|
||||||
|
@ -102,7 +110,7 @@
|
||||||
; This is meant to be used on systems where some external system like
|
; This is meant to be used on systems where some external system like
|
||||||
; Monit will restart any instance that exits, thereby making the shutdown
|
; Monit will restart any instance that exits, thereby making the shutdown
|
||||||
; into a restart.
|
; into a restart.
|
||||||
;InworldRestartShutsDown = false
|
InworldRestartShutsDown = false
|
||||||
|
|
||||||
; ##
|
; ##
|
||||||
; ## PRIM STORAGE
|
; ## PRIM STORAGE
|
||||||
|
@ -227,7 +235,6 @@
|
||||||
|
|
||||||
; If enabled, enableFlySlow will change the primary fly state to
|
; If enabled, enableFlySlow will change the primary fly state to
|
||||||
; FLYSLOW, and the "always run" state will be the regular fly.
|
; FLYSLOW, and the "always run" state will be the regular fly.
|
||||||
|
|
||||||
enableflyslow = false
|
enableflyslow = false
|
||||||
|
|
||||||
; PreJump is an additional animation state, but it probably
|
; PreJump is an additional animation state, but it probably
|
||||||
|
@ -236,7 +243,6 @@
|
||||||
|
|
||||||
; This is commented so it will come on automatically once it's
|
; This is commented so it will come on automatically once it's
|
||||||
; supported.
|
; supported.
|
||||||
|
|
||||||
; enableprejump = true
|
; enableprejump = true
|
||||||
|
|
||||||
; Simulator Stats URI
|
; Simulator Stats URI
|
||||||
|
@ -265,6 +271,7 @@
|
||||||
DelayBeforeAppearanceSave = 5
|
DelayBeforeAppearanceSave = 5
|
||||||
DelayBeforeAppearanceSend = 2
|
DelayBeforeAppearanceSend = 2
|
||||||
|
|
||||||
|
|
||||||
[SMTP]
|
[SMTP]
|
||||||
enabled=false
|
enabled=false
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,12 @@
|
||||||
; 0 to disable
|
; 0 to disable
|
||||||
HitRateDisplay = 100
|
HitRateDisplay = 100
|
||||||
|
|
||||||
; Set to false for disk cache only.
|
; Set to false for no memory cache
|
||||||
MemoryCacheEnabled = false
|
MemoryCacheEnabled = false
|
||||||
|
|
||||||
|
; Set to false for no file cache
|
||||||
|
FileCacheEnabled = true
|
||||||
|
|
||||||
; How long {in hours} to keep assets cached in memory, .5 == 30 minutes
|
; How long {in hours} to keep assets cached in memory, .5 == 30 minutes
|
||||||
; Optimization: for VPS or limited memory system installs set Timeout to .016 (1 minute)
|
; Optimization: for VPS or limited memory system installs set Timeout to .016 (1 minute)
|
||||||
; increases performance without large memory impact
|
; increases performance without large memory impact
|
||||||
|
|
|
@ -2985,6 +2985,7 @@
|
||||||
<Files>
|
<Files>
|
||||||
<!-- SADLY the way this works means you need to keep adding these paths -->
|
<!-- SADLY the way this works means you need to keep adding these paths -->
|
||||||
<Match path="Agent/TextureSender/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="Agent/TextureSender/Tests" pattern="*.cs" recurse="true"/>
|
||||||
|
<Match path="Asset/Tests" pattern="*.cs" recurse="true"/>
|
||||||
<Match path="Avatar/Inventory/Archiver/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="Avatar/Inventory/Archiver/Tests" pattern="*.cs" recurse="true"/>
|
||||||
<Match path="Framework/InventoryAccess/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="Framework/InventoryAccess/Tests" pattern="*.cs" recurse="true"/>
|
||||||
<Match path="World/Archiver/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="World/Archiver/Tests" pattern="*.cs" recurse="true"/>
|
||||||
|
@ -3029,6 +3030,7 @@
|
||||||
<Reference name="OpenSim.Region.CoreModules"/>
|
<Reference name="OpenSim.Region.CoreModules"/>
|
||||||
<Reference name="OpenSim.Region.OptionalModules"/>
|
<Reference name="OpenSim.Region.OptionalModules"/>
|
||||||
<Reference name="OpenSim.Region.Physics.Manager"/>
|
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||||
|
<Reference name="OpenSim.Services.AvatarService"/>
|
||||||
<Reference name="OpenSim.Services.Interfaces"/>
|
<Reference name="OpenSim.Services.Interfaces"/>
|
||||||
|
|
||||||
<!-- Unit tests -->
|
<!-- Unit tests -->
|
||||||
|
@ -3052,6 +3054,7 @@
|
||||||
<Files>
|
<Files>
|
||||||
<!-- SADLY the way this works means you need to keep adding these paths -->
|
<!-- SADLY the way this works means you need to keep adding these paths -->
|
||||||
<Match path="Avatar/XmlRpcGroups/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="Avatar/XmlRpcGroups/Tests" pattern="*.cs" recurse="true"/>
|
||||||
|
<Match path="World/NPC/Tests" pattern="*.cs" recurse="true"/>
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue